首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么参数匹配对非模板版本有效,而对模板版本不起作用?

为什么参数匹配对非模板版本有效,而对模板版本不起作用?
EN

Stack Overflow用户
提问于 2012-10-05 11:44:03
回答 2查看 154关注 0票数 1

考虑这个非常简单的例子,其中我有一个模板包装类,其中定义了操作符:

代码语言:javascript
复制
template <class T>
struct W {
   W(const T&) {}
};
template <class T> 
T operator + (const W<T>& w1, const W<T>& w2) { return T(); }

这令人惊讶地无法与包装类型匹配,而gcc4.5.1中的简单错误无法找到operator + (A,A)

代码语言:javascript
复制
struct A {};
int main() {
  A a1, a2;
  A a3 = a1 + a2;
}

我尝试通过测试非模板包装器来找到原因,但是这个版本有效:

代码语言:javascript
复制
struct A {};
struct WA {
   WA(const A&) {}
}; 
A operator + (const WA& w1, const WA& w2) { return A(); }
int main() {
  A a1, a2;
  A a3 = a1 + a2;
}

参数匹配差异的原因是什么,如何使模板版本工作?

更新

我把你的答案考虑进去了,我把这个例子改成了一个相反的例子,结果仍然是一样的--模板版本是在抱怨缺少操作符+,而非模板工作得很好。现在,我有了显式包装类的显式强制转换操作符:

模板版本

代码语言:javascript
复制
template <class T>
struct W {
};
template <class T> 
T operator + (const W<T>& w1, const W<T>& w2) { return T(); }

struct A {
 operator W<A>() const { return W<A>(); }
};

非模板

代码语言:javascript
复制
struct WA {
}; 
struct A {
 operator WA() const { return WA(); }
};

A operator + (const WA& w1, const WA& w2) { return A(); }

我试图避免这种解决办法:

代码语言:javascript
复制
A a3 = W(a1) + W(a2);

这没希望了吗?

代码语言:javascript
复制
A a3 = a1 + a2;
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-05 11:58:20

模板参数演绎在过载解析之前。但是模板参数演绎不考虑隐式转换,因此模板化运算符甚至从未被考虑过。

隐式转换仅在选择过载后应用。

不过你可以说是A a3 = W(a1) + W(a2);

票数 4
EN

Stack Overflow用户

发布于 2012-10-05 12:05:18

您的第一个示例失败了,因为标准说它必须在模板中失败。与参数相关的名称查找存在潜在问题,而模板则加剧了这些问题。其中一种方法是防止模板进行这种查找,除非您对模板的使用有明确的了解。以下是C++03标准14.8.1节第6段的相关案文:

对于简单的函数名,即使函数名在调用的范围内不可见,参数依赖的查找(3.4.2)也适用。这是因为调用仍然具有函数调用的语法形式(3.4.1)。但是,当使用带有显式模板参数的函数模板时,调用没有正确的语法形式,除非在调用点上有一个具有该名称的函数模板。如果没有这样的名称是可见的,则调用在语法上不具有良好的格式,并且不适用与参数相关的查找。如果这样的名称是可见的,则会应用与参数相关的查找,并在其他命名空间中找到其他函数模板。

更新:

这一问题是经过编辑的,并附有补充资料。

我试图避免这种解决办法: A a3 = W(a1) + W(a2);

你为什么要避免这种情况?您的这段代码违反了编程的两个关键规则。

  1. 代码好像下一个维护你代码的人是一个杀人的疯子,他知道你住在哪里。
  2. 最小惊讶原则。

即使你的非模板版本也违反了这些规则。您可以通过(隐藏)转换到不相关的类( a1+a2 )来计算W,该类的operator+返回A而不是W。这并不是最不惊讶的原则。至少可以说,这是令人吃惊的。为什么你不认为将你的转换明确化是一个更好的方法呢?

与参数相关的查找是一个非常强大的工具,但是与此功能相关的问题很多。将ADL与自动类型转换结合起来,使问题放大。将其与自动类型转换和模板相结合,就会造成混乱。标准委员会认为已经够了。除非将转换显式化,否则不能执行想要做的事情。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12745569

复制
相关文章

相似问题

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