首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >显式模板专门化问题

显式模板专门化问题
EN

Stack Overflow用户
提问于 2010-10-31 08:33:09
回答 3查看 352关注 0票数 3
代码语言:javascript
运行
复制
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.
}

链接器错误为

代码语言:javascript
运行
复制
error LNK2019: unresolved external symbol "public: void __thiscall
Test<int>::f<char>(void)"

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

测试f()

我可以通过定义另一个函数来解决错误,如下所示。

代码语言:javascript
运行
复制
template<>
template<> void Test<int>::f<char>(){}

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-10-31 08:51:43

C++03,第14.7.3/2节:

显式专门化应在模板是其成员的名称空间中声明,对于成员模板,则在其名称空间中声明封闭类或封闭类模板为成员。类模板的成员函数、成员类或静态数据成员的显式专门化应在类模板所属的名称空间中声明。

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

代码语言:javascript
运行
复制
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>();
}
票数 5
EN

Stack Overflow用户

发布于 2010-10-31 11:59:23

您面临的问题是,您已经在f模板中声明了char的专门化,这是不正确的。编译器没有检测到错误,但是您想要在所有模板实例化中为f提供char的专门化,这让它感到困惑和解释:

代码语言:javascript
运行
复制
template <typename T>
struct Test {
   template <typename U> void f();
   template <> void f<char>();       // <- Incorrect
};

编写Test<int>时,编译器实例化模板,并(错误地)接受它,并表示charTest<int>中有一个专门化。

只要删除这一行,您就可以编译代码了。它将只对Test<char>::f<char>()使用专门化,我不确定这是否是您想要的。

如果您的意图是为所有实例化类型的f专门化char,则不允许这样做。定义模板专门化时,所有封装的模板都是专门化的。常见的工作不是提供专门化,而是提供成员函数的不同过载:

代码语言:javascript
运行
复制
template <typename T>
struct Test {
   template <typename U> void f( U );
   void f( char );
};

但这对您没有多大帮助,因为您不能为相同的参数提供不同的重载(在您的例子中没有参数)。此外,在您的情况下,您必须显式调用模板以区分,并且显式请求模板的代码不会获取重载:

代码语言:javascript
运行
复制
int main() {
   Test<int> t;
   t.f<char>(); // will call template, not "void f(char)"!!
}

如果没有更多关于你真正想要实现的目标的细节,我就无法思考这个问题的其他潜在解决方案。

票数 3
EN

Stack Overflow用户

发布于 2010-10-31 08:44:46

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

为什么你需要一个明确的专业化?为什么你不必要地想让你的代码变得复杂?

以下内容适用于您列出的所有组合。

代码语言:javascript
运行
复制
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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4062388

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档