我拼命想让我的专业化工作,但仍然有不可编译的代码,因为推断出不正确的参数.请注意,错误不是关于定义模板,而是关于在错误的模板实现中应用不相关的操作.代码演示的问题的简化示例是:
struct Test { void Method() const {} };
template<typename T>
void Cmp(T _val) { _val > 1; }
template<>
void Cmp<const Test &>(const Test &_val) { _val.Method(); }
template<>
void Cmp<const char *>(const char *_val) { _val[2]; }
int main()
{
Test test1;
char test2[5];
Cmp(10); // ok, expected
Cmp(test1); // error in Cmp(T)?! but expecting to instantiate Cmp(const Test &)
Cmp(test2); // error in Cmp(T)?! but expecting to instantiate Cmp(const char *)
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我真的不希望使用像Cmp<const Test &>(test1)(有效)的显式调用作为AFAIK,编译器应该能够自动推断出参数,这些特化背后的整个想法是透明地调度Cmp调用(在实际代码中,我是定义运算符) .当然,按价值专业化Cmp<Test>(Test)按预期工作,但对于大型复杂的非POD类,按价值传递它是荒谬的.
无论我尝试应用编译器的任何修复,只是顽固地拒绝使用通用模板来选择引用特化.似乎我遗漏了一些重要的东西但是我真的没有想法为什么我的方法不起作用以及我应该如何从非模板化的C++世界构建表达这样一个简单概念的代码作为通过引用传递类.当然,谷歌证明对这个问题完全没用.^ _ ^我尝试了GCC 4.2.1和4.4.6.
Jam*_*lis 13
Cmp(test1);
Run Code Online (Sandbox Code Playgroud)
在这里,T从论证推断出来Test.它并不是const Test&因为你的专业化不匹配,因此主要模板被实例化的原因.您需要使您的专业化Test取值.有了这个声明,确实使用了专业化:
template<>
void Cmp<Test>(Test _val) { _val.Method(); }
Run Code Online (Sandbox Code Playgroud)
Cmp(test1);
Run Code Online (Sandbox Code Playgroud)
在这里,T推断是char*,不是const char*,所以专业化不匹配.你需要专门化char*而不是const char*匹配它.或者,您可以将参数转换为const char*进行调用时:
const char* test2ptr = test2;
Cmp(test2ptr);
Run Code Online (Sandbox Code Playgroud)
所有这一切,为什么当你可以超负荷时专注?
template<typename T>
void Cmp(T _val) { _val > 1; }
void Cmp(const Test &_val) { _val.Method(); }
void Cmp(const char *_val) { _val[2]; }
// Add an overload to support arrays of char:
template <unsigned N>
void Cmp(const char (&_val)[N]) { _val[1]; }
Run Code Online (Sandbox Code Playgroud)
你真的应该避免专门化功能模板. 这很困难,在大多数情况下是不值得的麻烦.