编译器选择错误的模板功能专业化

时间:2011-06-21 04:13:04

标签: c++ templates

我正在拼命尝试让我的专业化工作,但由于推断出不正确的参数,我仍然拥有不可编译的代码。请注意,错误不是关于定义模板,而是关于在错误的模板实现中应用不相关的操作。演示该问题的代码的简化示例是:

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

我真的不希望使用像Cmp<const Test &>(test1)这样的显式调用(有效)作为AFAIK,编译器应该能够自动推断出参数,这些特化背后的整个想法是透明地调度Cmp调用(实际上)代码,我正在定义运算符)。当然,按值专业化Cmp<Test>(Test)按预期工作,但对于大型复杂的非POD类,按值传递它是荒谬的。

无论我尝试应用编译器的任何修复,只是顽固地拒绝使用通用模板来选择按引用的特化。似乎我遗漏了一些重要的东西但是我真的没有想法为什么我的方法不起作用以及我应该如何从非模板化的C ++世界构建表达这样一个简单概念的代码作为通过引用传递类。当然,谷歌证明对这个问题完全没用。 ^ _ ^我尝试了GCC 4.2.1和4.4.6。

2 个答案:

答案 0 :(得分:12)

Cmp(test1);

此处,T从参数推断为Test。它不是推断为const Test&所以你的专业化不匹配,因此主要模板被实例化的原因。您需要使您的专业化按值Test。通过此声明,确实使用了专业化:

template<>
void Cmp<Test>(Test _val) { _val.Method(); }

Cmp(test1);

此处,T推断为char*,而不是const char*,因此专精化不匹配。您需要专门针对char*而非const char*进行匹配。或者,您可以在拨打电话时将参数转换为const char*

const char* test2ptr = test2;
Cmp(test2ptr); 

所有这一切,为什么当你能够超载时专注于什么?

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]; }

You really should avoid specializing function templates.这很困难,而且在大多数情况下都是不值得的。

答案 1 :(得分:4)

嗯...为什么专攻?只是超载它..

void Cmp(const Test &_val) { _val.Method(); }

void Cmp(const char *_val) { _val[2]; }

100%保证选择这些方法。