2010-02-19 91 views
4

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

#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; 
} 
+2

如果你打算继续'使用命名空间标准;'你为什么要继续澄清'std :: string'? – 2010-02-19 08:33:21

回答

8

你面临的问题(除了operator std::string()返回一个布尔值)是隐式转换触发,当你想要和当你不需要。

当编译器看到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既不是他们的,所以它试图转换的东西,可以适应,发现两条路径:转换为可以升级到char或直接转换为std::string的bool。编译器不能真正决定并放弃。

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

这个article专门处理这个问题。该建议是,而不是提供一个转换到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); 
    } 
}; 

只有当读者想知道如何safe_bool成语实现并读取它们填充的头部将面临的复杂性(可在注释中解释)

+0

提到safe_bool成语的问题无关。大多数情况下,你并不是真的想要一个布尔值,你只是想写'if' test :) – 2010-02-19 09:13:28

+0

我假设bool正在通过整数提升转换为char,因为标准没有提到任何关于布尔转换为char。 引用:“一个bool类型的右值可以转换为int类型的右值,其中false为零且真正成为一个。” – piotr 2010-02-19 09:36:12

+0

非常有趣的文章,但我发现它使用这样的代码如果测试,如果它是非常不可读的,它打败了添加可读性的目的。另外辅助函数应该是const。 – piotr 2010-02-19 10:20:33

4

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

+0

它返回一个字符串'std :: string(static_cast (true))' – MSalters 2010-02-19 08:42:22

+0

修正了错字,但与 – piotr 2010-02-19 09:01:08

1

正如David Rodriguez正确指出的那样,可以将bool升级为char a nd你得到一个ambigous超载。

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

while (istream.getline()) { 
} 

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

有些人认为这不是一个解决方案,从理论上说好一个可以做

void* streamptr = istream; 
delete streamptr; 

但在我看来,如果有人开始删除这样的三分球......他不应该被允许任何接近stl代码(或C++)的地方。

相关问题