明确的模板专业化问题

时间:2010-10-31 08:33:09

标签: c++

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.
}

链接器错误

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

我的要求是:我应该能够将任何类型传递给Test类,并将任何类型传递给函数f()。我应该可以使用下面所有类型的组合。

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

我可以通过定义下面的另一个函数来解决错误。

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

但是,将Test类作为模板的用途是什么?如何让它适用于所有组合?

3 个答案:

答案 0 :(得分:5)

C ++ 03,§14.7.3/ 2:

应在名称空间中声明显式特化 template是成员,或者,对于成员模板,在其名称空间中 封闭类或封闭类模板是成员。 成员函数,成员类或静态数据的显式特化 类模板的成员应在其名称空间中声明 类模板是成员。

因此,您应该在类之外声明您的专业化,例如:

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 :(得分:3)

您遇到的问题是您已在f模板中声明了char Test的专业化,这是不正确的。编译器没有检测到错误,但是在所有模板实例化中,您希望为f char提供template <typename T> struct Test { template <typename U> void f(); template <> void f<char>(); // <- Incorrect }; 的特化,这让您感到困惑和解释:

Test<int>

当您编写f时,编译器会实例化模板,并且(错误地)接受该模板并解释charTest<int>的{​​{1}}的专门化。< / p>

删除该行,您将获得要编译的代码。它将仅对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)"!!
}

如果没有关于你真正想要达到的目标的更多细节,我无法考虑其他可能解决问题的方法。

答案 2 :(得分:0)

  

我的要求是:我应该能够将任何类型传递给Test类,并将任何类型传递给函数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
}