2014-01-25 167 views
4

我回答this question,有关用户定义的转换到bool以及如何的话题比较禁用其他转换:隐式转换为布尔值,并与布尔文字

struct foo 
{ 
    operator bool() const //Explicit overload for bool 
    { 
     return true; 
    } 

    template<typename T> 
    operator T() const = delete; //Everithing which is not a bool (Everithing which 
           //does not fit in the explicit overload) would 
           //resolve to this operator and will fail. 
}; 


int main() 
{ 
    foo f; 

    bool b = f; //OK 
    int i = f; //ERROR 
    char c = f; //ERROR 
    etc... 
} 

后来,OP问我为什么喜欢if(f == true)条件语句失败(凡ffoo我试图通过我自己和我吃惊,因为与布尔文字是比较导致转换到int(这是禁用的),而不是bool

int main() 
{ 
    foo f; 

    if(f); //OK, converts to bool 
    if(f == true); //ERROR: Conversion to int, which has been disabled 
} 

prog.cpp:20:12: error: use of deleted function ‘foo::operator T() const [with T = int]’ if(f == true);
..............................................................................................................................................^

我的问题是:是布尔文字定义为整数(如常见的C宏#define true 1 #define false 0),如果没有,为什么比较铅为int的转换,而不是bool

我在启用C++ 11的情况下使用GCC4.8.1(-std=C++11)。

Here是ideone行为的一个例子。

+1

注有一个在之间的相关例子的有趣差异并[g ++ 4.8.1](HTTP://coliru.stacked- [CWG 954](http:// www。com/cn/b2865b8fea3021b4)和[clang ++ 3.5](http://coliru.stacked-crooked.com/a/cc3c7a74ee58d588) – dyp

+1

这可能是标准中的缺陷, //www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#954)(open issue),特别是注释*“有些实现明确地选择了int类型候选。被调整来选择L和R是相同类型的候选人?“*(这是我答案中缺失的部分) – dyp

回答

2

由于foo是类类型,特殊规则使用不是专门为该类类型定义的操作时,适用,见[over.built]/12

For every pair of promoted arithmetic types L and R , there exist candidate operator functions of the form

LR operator*(L, R); 
LR operator/(L, R); 
LR operator+(L, R); 
LR operator-(L, R); 
bool operator<(L, R); 
bool operator>(L, R); 
bool operator<=(L, R); 
bool operator>=(L, R); 
bool operator==(L, R); 
bool operator!=(L, R); 

where LR is the result of the usual arithmetic conversions between types L and R .

不是使用术语提升的算术类型:这需要bool的促销。

bool被提升到int,见[conv.prom]/6(积分促销)

A prvalue of type bool can be converted to a prvalue of type int , with false becoming zero and true becoming one.


所以有形式的候选函数

common_type<L,int> operator==(L, int); 

其中L是一种推广的算术类型。然而,有许多人,例如

common_type<int  , int> operator==(int  , int); 
common_type<long  , int> operator==(long  , int); 
common_type<long long, int> operator==(long long, int); 

每个这些都需要从foo到促进类型的用户定义的转换。我不清楚为什么这不是含糊不清的,因为foo可以转换为其中的任何一个。这在开放问题CWG 954中也有描述。

如果存在多个非模板转换函数,则g++4.8.1clang++3.5会报告此含糊性。 (应当指出的是,铛可能有一个错误在这里,看到this example工作正常使用g ++ 4.8.1。)


然而,没有形式

common_type<bool, int> operator==(bool, int); 

候选如bool而不是推广的算术类型。因此,从foobool转换将被选择用于表达

foo x; 
x == true 
+0

我想,答案并不完整。还有一块失踪。 – dyp

+0

我已经注意到了。我在等待:) – Manu343726

+0

@ Manu343726这篇文章缺失的是一些声明,说类类型确实需要转换为与提升的“bool”相同的类型。它可能有点微妙,例如内置的'operator =='需要在左侧和右侧有相同的类型。 – dyp

0

类型bool是而不是#在C++中定义。我认为比较提升到int并且需要int转换。

+0

那就是我的想法,我知道bool文字不是'#define'd。只是这种行为让我感到惊讶。任何人都有提到标准的说法? – Manu343726

+0

将bool转换为int来进行比较。我没有参考标准(需要下载,嗯......),但我非常确定,bool => int结合缺少类foo的int转换是错误的根源。 – rholmes

0

让我们在这里做一个简单的测试:

template <typename T> 
struct OutputType; 

int main() 
{ 
    OutputType<decltype(true)> a; 
} 

ATLEAST ideone这里输出的是truebool类型:http://ideone.com/Gm653T

但是:

The type bool can be converted to int with the value false becoming ​0​ and true becoming 1.

来源:cppreference

一个第二我的猜测是,正是这样的促销发生在这里