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

时间:2010-02-19 08:29:18

标签: 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;
}

3 个答案:

答案 0 :(得分: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 );

现在,t既不是它们,所以它会尝试转换为适合的东西,并找到两条路径:转换为可以提升为{{1}的bool或直接转换为char。编译器无法真正决定和放弃。

这是您希望避免提供许多不同转换运算符的原因之一。当您认为不应该被编译器隐式调用的任何东西时都会被调用。

article专门处理此问题。建议不是提供转换为std::string,而是提供对成员函数的转换

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; }; )内使用此类的实例,编译器将尝试转换为可在条件中使用的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;
}

只有当读者有兴趣知道如何实现// each class with conversion class testable { public: operator bool_type() { return safe_bool(true); } }; 成语并读取标题时,他们才会面临复杂性(可以在评论中解释)

答案 1 :(得分:4)

你的运算符std :: string()需要返回一个字符串,而不是bool。

答案 2 :(得分:1)

正如大卫罗德里格斯正确指出的那样,bool可以提升为char而你会得到一个过度的超负荷。

在stl中,使类可测试通常是通过转换为void *来完成的,例如当你做的时候

while (istream.getline()) {
}

循环条件解析为false,因为istream在其operator void*中返回NULL。

有些人认为这不是理论上可以做到的解决方案的好处

void* streamptr = istream;
delete streamptr;

但是在我看来,如果有人开始删除这样的指针......他不应该被允许在stl代码附近(或C ++)。