模板中的隐式转换和编译器强制

时间:2011-02-16 03:01:41

标签: c++ templates operator-overloading

我有这个非常简单的包装模板:

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更改为intdoublebool或任何原始的,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

3 个答案:

答案 0 :(得分:1)

操作符T被称为“转换操作符”或“转换函数”而不是强制转换。 “转化”是隐含的;铸造是明确的。

编译器找不到operator == for std :: string,因为重载决策规则不允许这种情况发生。关于你真正想要做的事情的更多细节可以帮助提供解决方案。

答案 1 :(得分:0)

显然这是一个GCC 4.5错误。代码是有效的,不像Fred Nurk所说的那样。

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45383

答案 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);

我们有它。它首先需要进行模板参数推导,Aconst basic_string<>不匹配的事实将使得operator==被忽略。你很幸运,无论如何都使用ADL找到了operator==,这样它首先会进行参数推导(因为std::string是你的类型的模板参数,它会考虑ADL命名空间std并找到这个运算符)。

所以我们没有合适的operator==来调用,因此GCC对于拒绝你的代码是好的,因为@Fred给出的原因很简单。最后,尝试使类表现得像另一种类型被认为是失败的。