Почему компилятор запрещает такую специализацию?

Хочу сделать специализацию метода для отдельного контейнера и ввожу такой код:

template<typename type, typename container>
struct A
{
    void say();
};

template<typename type, typename container>
void A<type, container>::say()
{
    std::cout << "Say for all" << std::endl;
}

template<typename type>
void A<type, std::vector<type>>::say()
{
    std::cout << "Say for vector" << std::endl;
}

Однако компилятор выдает ошибку:

invalid use of incomplete type 'struct A<type, std::vector >' void A<type, std::vector>::say()


Ответы (2 шт):

Автор решения: Harry

Вы специализируете член, но не саму структуру. Вот он и не понимает — а где сама структура?

Вот такое вполне работает:

template<typename type, class container>
struct A
{
    void say() { std::cout << "Say for all" << std::endl;}
};

template<typename type>
struct A<type,vector<type>>
{
    void say()
    {
        std::cout << "Say for vector" << std::endl;
    }
};

int main(int argc, char * argv[])
{
    A<int,vector<int>> a;
    A<int,double> b;
    a.say();
    b.say();
}
→ Ссылка
Автор решения: user7860670

Специализация одного члена шаблона класса не разрешается. Для этого надо специализировать весь класс. Однако в данном случае оно и не нужно, так как специализация будет полностью совпадать с основным классом, а все различие сводится к реализации функции say. В таком случае следует использовать if constexpr:

#include <type_traits>

template<typename type, typename container>
struct A
{
    void say(void)
    {
        char const * psz_message{};
        if constexpr (::std::is_same_v<container, ::std::vector<type>>)
        {
            psz_message = "Say for vector";
        }
        else
        {
            psz_message = "Say for all";
        }
        ::std::cout << psz_message << ::std::endl;
    }
};
→ Ссылка