2010-10-31 3 views
3
template <class T> 
class Test 
{ 
public: 
    template<class U> void f(); //generic function 

    template<> void f<char>(); //Specialization for char. 
}; 

template <class T> 
template<class U> 
void Test<T>::f() //Definition of generic function 
{ 
} 

template<> 
template<> void Test<char>::f<char>(){} //Definition of specialization. 

int main() 
{ 
    Test<char> ob1; 
    ob1.f<char>(); //Works fine. 

    Test<int> ob2; 
    ob2.f<char>(); //Produces linker error. 
} 

Linker ошибкаЯвная специализация шаблона выпуск

error LNK2019: unresolved external symbol "public: void __thiscall 
Test<int>::f<char>(void)" 

Мое требование: я должен быть в состоянии пройти любого типа для тестирования класса и любого типа для функции Р(). Я должен иметь возможность использовать все комбинации типов, как показано ниже.

Test f() 
    -------------- 
    int char 
    char int 
    int int 

я могу решить эту ошибку, определив другую функцию, как показано ниже.

template<> 
template<> void Test<int>::f<char>(){} 

Но что же такое использование класса Test в качестве шаблона? Как заставить его работать для всех комбинаций?

+1

Было бы целесообразно, чтобы добавить, что ожидаемый метод будет выполнять для каждого элемента таблицы. То есть 'Test :: f ()' должен быть действительным и вызвать: a) общую реализацию, b) специализацию? –

ответ

5

C++ 03, §14.7.3/2:

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

Поэтому вы должны объявить специализацию за пределами класса, например:

template <class T> 
class Test 
{ 
public: 
    template<class U> void f(); //generic function 
}; 

template <class T> 
template <class U> 
void Test<T>::f() {} //Definition of generic function 

template<> 
template<> 
void Test<char>::f<char>(){} //Specialization. 

int main() 
{ 
    Test<char> ob1; 
    ob1.f<char>(); 

    Test<int> ob2; 
    ob2.f<char>(); 
} 
+1

Не нужно специализировать 'Test <>' для 'char', если вам нужно только специализироваться' Test :: f ': вы можете удалить специализацию' Test ' и просто предоставить: 'template <> template < > void Test :: f () {} ', чтобы специализироваться только на этой функции в этом конкретном экземпляре шаблона. –

+0

@ "David Rodríguez - dribeas": Право, специализация Тест не нужен. Спасибо за указание на это. – vitaut

0

Мое требование: я должен иметь возможность передавать любые типы Test Class и любой тип функции f(). Я должен иметь возможность использовать все комбинации типов, как показано ниже.

Зачем вам нужна специальная специализация? Почему вы излишне хотите сделать свой код сложным?

Следующие работы для всех комбинаций, которые вы указали.

template <class T> 
class Test 
{ 
public: 
    template<class U> void f(); 
}; 

template <class T> 
template<class U> 
void Test<T>::f(){} 

int main() 
{ 
    Test<char> ob1; 
    ob1.f<char>(); //Works fine. T = char, U = char 

    Test<int> ob2; 
    ob2.f<char>(); //Works fine T = int, U = char 
} 
+0

@Saurav: Если я хочу иметь другую реализацию в f (), мне нужно сделать специализацию. Однако я делаю это исключительно для обучения. – bjskishore123

3

Проблема, с которой вы столкнулись, что вы объявили о специализации f для char в Test шаблоне, и это неверен. Компилятор не обнаруживает ошибку, но путаются и интерпретация, что вы хотите, чтобы обеспечить специализацию f для char в всех конкретизации шаблона:

template <typename T> 
struct Test { 
    template <typename U> void f(); 
    template <> void f<char>();  // <- Incorrect 
}; 

Когда вы пишете Test<int> компилятор конкретизирует шаблон и (ошибочно) принимает его и интерпретирует, что существует специализация f для char в Test<int>.

Просто удалите строку, и вы получите код для компиляции. Он будет использовать специализацию только для Test<char>::f<char>(), и я не уверен, что это то, что вы хотите.

Если ваше намерение специализируется f для char с все инстанцировании типов, что не допускается. Когда вы определяете специализацию шаблона, все охватывающие шаблоны должны быть специализированными. Обычная работа вокруг не обеспечивая специализацию, но другую перегрузку функции члена:

template <typename T> 
struct Test { 
    template <typename U> void f(U); 
    void f(char); 
}; 

Но это не поможет вам много там, так как вы не можете обеспечить различные перегрузки для одних и тех же аргументов (в вашем случае нет аргументов). Кроме того, в вашем случае вы должны явно вызвать шаблон дифференцироваться, и код, который явно просит шаблон не подобрать перегрузки:

int main() { 
    Test<int> t; 
    t.f<char>(); // will call template, not "void f(char)"!! 
} 

Без получения более подробной информации о том, что вы действительно хотите достичь, я не могу думать о другом потенциальное решение проблемы.