简体   繁体   English

奇怪的运算符重载行为?

[英]Strange operator overloading behavior?

#include <iostream>
using namespace std;

class Foo{

        string _s;
        public:
        Foo(string ss){
                _s = ss;
        }
        Foo& operator=(bool b){
                cout << "bool" << endl;
                return *this;
        }
        Foo& operator=(const string& ss){
                cout << "another one" << endl;
                return *this;
        }
};


int main(){

        Foo f("bar");
        f = "this";
        return 0;

}

I have overloaded = operator. 我有重载=运算符。 I expected f = "this"; 我期待f = "this"; statement to call operator=(const string& ss) overload. 语句调用operator=(const string& ss)重载。 But it does not. 但事实并非如此。 It calls operator=(bool b) overload. 它调用operator=(bool b)重载。 Why? 为什么?

这个operator operator=(const string& ss)需要转换用户定义的参数类型( const char*std::string ),而bool版本没有,所以提供了更好的匹配:你从内置转换-in类型const char[5]const char*bool

As noted by another answer, the pointer-to-char to bool conversion is preferred because it involves no user-defined conversions, while the std::string conversion has a user-defined conversion in it. 正如另一个答案所指出的那样,指向bool转换的指针是首选,因为它不涉及用户定义的转换,而std::string转换中包含用户定义的转换。

C++11 offers the ability to do manual type control. C ++ 11提供了手动类型控制的功能。

template<size_t n>
struct enumarated_enum {
private:
  enum empty {};
};

template<bool b, size_t n=0>
using EnableIf = typename std::enable_if< b, typename enumerated_enum<n>::empty >::type;

template<typename String, EnableIf< std::is_convertible< String, std::string >::value >... >
Foo& operator=(String&& s) {
  cout << "string overload" << "\n";
}

// either this:
template<typename Bool, EnableIf< !std::is_convertible< Bool, std::string >::value && std::is_convertible< Bool, bool >::value, 1 >... >
Foo& operator=(Bool&& b) {
  cout << "bool overload" << "\n";
}
// or this:
Foo& operator=(bool b) {
  cout << "bool overload" << "\n";
}

where we match a type perfectly if it can be converted to a std::string , and the template doesn't match if it cannot be converted to std::string and other overloads are looked at. 我们完全匹配类型,如果它可以被转换成std::string ,和模板不匹配,如果它不能被转换成std::string和其他重载的看着。

If you have many types you want to be able to support, you have to use long logical forms that describe which of the overloads you want to run, and make sure the others don't accept it (with the not construct above). 如果您希望能够支持多种类型,则必须使用描述要运行哪些重载的长逻辑形式,并确保其他类型不接受它(使用上面的not构造)。 If you only have two types, the second type can be a traditional overload. 如果您只有两种类型,则第二种类型可以是传统的重载。 The template overload gets first crack at anything that doesn't match the traditional overload exactly... 模板重载首先在任何与传统过载完全不匹配的情况下得到破解......

(The second template argument is a variardic list of numbered enum s which cannot exist, whose only purpose is to make sure that the two templates differ in sufficient ways for the compiler not to complain.) (第二个模板参数是编号enum的变量列表,它不能存在,其唯一目的是确保两个模板的区别在于编译器不要抱怨的充分方式。)

Without delving into C++ standards, on the surface your problem is, you defined your assignment overload with string& and a bool but in your test you're assigning a char* array. 在没有深入研究C ++标准的情况下,表面问题是,您使用字符串&和bool定义了赋值重载,但在测试中,您正在分配char *数组。

So if you define a string and assign, it will work as expected. 因此,如果您定义一个字符串并赋值,它将按预期工作。

Check it working here : http://codepad.org/owb6noXR 检查它在这里工作: http//codepad.org/owb6noXR

As others have said, an easy fix to this is to simply cast your string to an std::string , when doing the operator, so C++ knows exactly which overload to choose: 正如其他人所说,一个简单的解决方法是在执行运算符时简单地将字符串转换为std::string ,因此C ++确切地知道要选择哪个重载:

#include <iostream>
using namespace std;

class Foo{

        string _s;
        public:
        Foo(string ss){
                _s = ss;
        }
        Foo& operator=(bool b){
                cout << "bool" << endl;
                return *this;
        }
        Foo& operator=(const string& ss){
                cout << "another one" << endl;
                return *this;
        }
};


int main(){

        Foo f((string)"bar");
        f = (string)"this";
        return 0;

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM