模板函数重载与const

时间:2015-05-13 21:50:00

标签: c++ templates

以下是一些代码:

template<class T>
inline void bar(T& t) {
   foo(t); // intention is that foo() is found by ADL
}

struct Wig {
   int i;
};

void foo(int){ }

// some convenience overload
inline void bar(const Wig& w) { foo(w.i);  }

// The bit that if uncommented, "fixes" the problem
//inline void bar(Wig& w) {   foo(w.i); }

int main()
{
   Wig w;
   bar(w);
   return 0;
}

Clang 3.5和Gcc 4.7,吐出以下错误:

template-function-overload.cpp:12:4: error: no matching function for call to 'foo'
   foo(t);
   ^~~
template-function-overload.cpp:29:4: note: in instantiation of function template specialization
      'bar<Wig>' requested here
   bar(w);
   ^
template-function-overload.cpp:19:6: note: candidate function not viable: no known conversion from
      'Wig' to 'int' for 1st argument
void foo(int){ }
     ^

所以它看起来不像编译器问题。

另外,注释掉非const重载会修复错误。

为什么这段代码不正确,以及为什么需要非const重载?

1 个答案:

答案 0 :(得分:7)

对于bar(w)调用,重载决策比较

void bar<Wig>(Wig&); // instantiated from the template
void bar(const Wig &);

绑定到较少cv限定类型的引用更好([over.ics.rank],bullet 3.2.6),因此选择第一个签名。该模板尝试在foo上调用Wig,但是没有这样的事情,因此错误。

由于额外的非常数超载,我们现在正在比较(加上比其中任何一个更糟的const Wig &):

void bar<Wig>(Wig&); // instantiated from the template
void bar(Wig&);

参数类型是相同的,因此通过对转换序列进行排序,两者无法区分,而[over.match.best] bullet 1.6中的tiebreaker选择非模板而不是函数模板专门化。