我有这个非常简单的包装模板:
template<class T>
struct wrapper {
inline operator T () {
return v;
}
inline wrapper(T v):v(v) { }
T v;
};
尝试将它与任何非基本类型一起使用(例如)依赖于定义模板的比较运算符看起来并不乐观:
std::string t = "test";
assert(t == t);
typedef wrapper<std::string> string_wrapper;
assert(string_wrapper(t) == string_wrapper(t));
GCC 4.4.5抱怨此错误:
error: no match for ‘operator==’ in ‘wrapper<std::basic_string<char> >(std::basic_string<char>(((const std::basic_string<char>&)((const std::basic_string<char>*)(& t))))) == wrapper<std::basic_string<char> >(std::basic_string<char>(((const std::basic_string<char>&)((const std::basic_string<char>*)(& t)))))’
有趣的是,GCC对模板进行三重投射,然后无法使用为operator ==
定义的std::string
。
我不认为隐式强制是不可能的,因为如果我将std::string
更改为int
或double
,bool
或任何原始的,GCC将选择正确的操作
我不想为包装器结构定义operator ==
,因为该运算符只是一个示例,我需要wrapper
'感觉'就像关于运算符的真实类型一样。
只是在演员GCC误解了我的语法,如果我创建一个包装器并尝试将其与自身进行比较,GCC再次抱怨(虽然没有三次转换)它找不到匹配的==运算符:
typedef wrapper<std::string> string_wrapper;
string_wrapper tw(t);
assert(tw == tw);
error: no match for ‘operator==’ in ‘tw == tw’
为什么GCC在std::string operator == std::string
提供演员时无法找到和/或使用wrapper
?
答案 0 :(得分:1)
操作符T被称为“转换操作符”或“转换函数”而不是强制转换。 “转化”是隐含的;铸造是明确的。
编译器找不到operator == for std :: string,因为重载决策规则不允许这种情况发生。关于你真正想要做的事情的更多细节可以帮助提供解决方案。
答案 1 :(得分:0)
显然这是一个GCC 4.5错误。代码是有效的,不像Fred Nurk所说的那样。
答案 2 :(得分:0)
提问者已经回答了一些海湾合作委员会的公关,但实际上并没有回答他的问题。
原因就像@Fred描述的那样。减少它:
template<typename T>
struct A {
operator T() { return T(); }
};
int main() {
A<std::string>() == A<std::string>();
}
编译器可以做什么?它可以在两个操作数上调用operator std::string()
然后进行比较。但为什么要首先做那个电话呢?首先需要找到一个operator==
,它有两个std::string
类型的参数。让我们看看它的运算符是如何定义的
template<class charT, class traits, class Allocator>
bool operator==(const basic_string<charT,traits,Allocator>& lhs,
const basic_string<charT,traits,Allocator>& rhs);
我们有它。它首先需要进行模板参数推导,A
与const basic_string<>
不匹配的事实将使得operator==
被忽略。你很幸运,无论如何都使用ADL找到了operator==
,这样它首先会进行参数推导(因为std::string
是你的类型的模板参数,它会考虑ADL命名空间std
并找到这个运算符)。
所以我们没有合适的operator==
来调用,因此GCC对于拒绝你的代码是好的,因为@Fred给出的原因很简单。最后,尝试使类表现得像另一种类型被认为是失败的。