operator bool()转换为std :: string并与运算符std :: string()冲突

pio*_*otr 4 c++ type-conversion

在类中声明运算符std :: string时,运算符bool()如何导致错误,并且还可以作为字符串的隐式转换?

#include <iostream>
#include <string>
using namespace std;

class Test {
public:
    operator std::string() { cout << "op string" << endl; return "whatever";}
    operator bool() { cout << "op bool" << endl; return true;}
};

int main(int argc, char *argv[]) {
    string s;
    Test t;
    s = t;
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*eas 8

您面临的问题(除了operator std::string()返回bool 之外)是隐式转换会在您需要时触发,而在您不需要时触发.

当编译器看到s = t它识别以下潜在std::operator=匹配时:

// using std::string for compactness instead of the full template
std::string::operator=( std::string const & ); 
std::string::operator=( char );
Run Code Online (Sandbox Code Playgroud)

现在,t它们都不是,所以它试图转换为适合的东西并找到两条路径:转换为可以升级charstd::string直接转换为bool的bool .编译器无法真正决定和放弃.

这是您希望避免提供许多不同转换运算符的原因之一.当您认为不应该被编译器隐式调用时,最终将调用任何内容.

文章这个问题专门处理.该建议不是提供转换bool,而是提供对成员函数的转换

class testable {
   typedef void (testable::*bool_type)();
   void auxiliar_function_for_true_value() {}
public:
   operator bool_type() const {
      return condition() ? &testable::auxiliar_function_for_true_value : 0;
   }
   bool condition() const;
};
Run Code Online (Sandbox Code Playgroud)

如果在condition(if (testable()))中使用此类的实例,编译器将尝试转换为bool_type可在条件中使用的实例.

编辑:

在评论代码如何使用此解决方案更复杂之后,您始终可以将其作为通用的小实用程序提供.提供代码的第一部分后,复杂性将封装在标头中.

// utility header safe_bool.hpp
class safe_bool_t;
typedef void (safe_bool_t::*bool_type)();
inline bool_type safe_bool(bool);

class safe_bool_t {
   void auxiliar_function_for_true_value() {}
   friend bool_type safe_bool(bool);
};
inline bool_type safe_bool(bool)
{
   return condition ? &safe_bool_t::auxiliar_function_for_true_value : 0;
}
Run Code Online (Sandbox Code Playgroud)

您的类现在变得更加简单,并且它本身是可读的(通过为函数和类型选择适当的名称):

// each class with conversion
class testable {
public:
   operator bool_type() {
      return safe_bool(true);
   }
};
Run Code Online (Sandbox Code Playgroud)

只有当读者有兴趣了解safe_bool成语如何实现并读取标题时,他们才会面临复杂性(可以在评论中解释)