Определение функции-члена явно специализированного класса вне определения класса

Я вижу ошибку, связанную с шаблонами (компилятор Visual Studio 2012), которые я не понимаю. Здесь код, сведенный к основному:

// Templated class - generic 
template <typename T>
class Test
{
    public:
        void WorksFine() {} // Comiples and works as expected at runtime
        void Problem();     
};

// Templated class - expicit specialization for T = int.
template <>
class Test<int>
{
        public:
            void WorksFine() {} // Comiples and works as expected at runtime
            void Problem();
};

// The definition below compiles and works fine at runtime.
template<typename T> void Test<T>::Problem() {}


// The definition below gives error C2910.
template<> void Test<int>::Problem() {printf("In Test::Problem(int instantiation)\n");}

Для метода WorksFine определение функции внутри явно специализированное определение класса, и все в порядке. Но для метода "Проблема", когда я определяю метод за пределами явно специализированного определения класса, я получаю ошибку C2910

Почему это? Ошибка C2910 указывает, что проблема в том, что Test:: Problem() уже определен. Но внутри класса определено not... определение функции не является объявлением.

Кажется довольно хромым, что можно что-то делать или нет, в зависимости от того, где вы решите поставить определение функции, которое я всегда был скорее решением стиля/синтаксиса, а не решением функциональности/семантики. Я что-то пропустил?

Ответ 1

Вам не нужен template<>. Просто напишите:

void Test<int>::Problem() {printf("In Test::Problem(int instantiation)\n");}

Синтаксис template<> для специализации участника требуется там, где явно создается экземпляр элемента самостоятельно; он опущен при определении члена уже существующей специализации.

template<typename T> struct X { static int i; };
template<> int X<int>::i = 0;  // member instantiation, uses template<>

template<typename T> struct Y { static int i; };
template<> struct Y<int> { static int i; }  // template specialization
int Y<int>::i = 0;  // no template<>

Ответ 2

Вам больше не нужно template в явном определении функции: void Test<int>::Problem() {printf("In Test::Problem(int instantiation)\n");}

В этом случае g++ дает немного лучшее сообщение об ошибке error: template-id 'Problem<>' for 'void Test<int>::Problem()' does not match any template declaration

Ответ 3

Попробуйте следующее:

// The definition below gives error C2910.
void Test<int>::Problem() 
{
    printf("In Test::Problem(int instantiation)\n");
}

int main()
{
    Test<int> hey; 

    hey.Problem(); 
    return 0;
};