返回语句中的C ++ 11显式转换运算符/构造函数

时间:2014-01-15 17:44:16

标签: c++ c++11 type-conversion implicit-conversion

我有一个以下示例(具有过度安全的布尔类型):

#include <cstdlib>

struct boolean_type
{

    explicit
    boolean_type(bool _value)
        : value_(_value)
    { ; }

    explicit
    operator bool () const
    {
        return value_;
    }

private :

    bool value_;

};

struct A
{

    A(int const _i) 
        : i_(_i)
    { ; }

    boolean_type operator == (A const & _other) const
    {
        return (i_ == _other.i_);
    }

private :

    int i_;

};

bool t()
{
    return A(0) == A(0);
}

int main()
{ 
    return EXIT_SUCCESS;
}

众所周知,这样的代码包含错误:“无法转换”(((int)((const A *)this) - &gt; A :: i_)==((int) other.A :: i ))'从'bool'到'boolean_type'“在bool A::operator == (A const &) const的return语句中”并且“无法在{{1的返回语句中将'boolean_type'转换为'bool'” }}。但这里有什么风险?为什么在这两种情况下都没有明确的转换?为什么隐含?事实上,我们在第二种情况下明确指定了返回类型bool t(),并且bool就是这样!

另外想说:

由于指定的障碍,我无法在我的用户代码中将static_assert(std::is_same< bool, decltype(std::declval< int >() == std::declval< int >()) >::value, "!");的所有条目替换为我的超级安全bool mocked-object ),因为,例如,在boolean_type使用上述结构的回报语句中,将那里视为隐式转换。类似的障碍并不是唯一的。

2 个答案:

答案 0 :(得分:3)

您有两个隐式转换。一个在这里:

return (i_ == _other.i_);

另一个在这里:

return A(0) == A(0);

这些是隐式的,因为您没有明确告诉编译器您希望将比较结果分别转换为boolean_typebool。不允许进行这些隐式转换,因为您同时创建了boolean_type explicit的构造函数和转换运算符 - 这就是explicit关键字的整个点。

您需要这样做:

return static_cast<boolean_type>(i_ == _other.i_);

return static_cast<bool>(A(0) == A(0));

明确转换为bool的典型原因是因为转换可能会在您不打算使用它的情况下使用。例如,如果您有boolean_type个名为b1的对象和b2次转化为非explicit的对象,则可以执行以下操作:

b1 > 0
b1 == b2

这些可能不是布尔转换运算符的预期用途。

答案 1 :(得分:0)

  

为什么在这两种情况下都没有明确的转换?

因为on ,程序员,如果你想要一个明确的转换,那就明确了。

如果您允许,隐式转换在这种情况下会起作用。但是,当您将operator boolboolean_type::boolean_type标记为explicit时,您不允许这样做。

  

为什么隐含?

因为你没有写转换。你必须:

  boolean_type operator == (A const & _other) const
  {   
      return boolean_type (i_ == _other.i_);
  }

...和

bool t()
{   
    return (bool) (A(0) == A(0));
}
  

但这里有什么风险?

你告诉我们。 explicit专门用于告诉编译器可能存在允许进行某些隐式转换的风险。因此,当您将这些函数标记为explicit时,您对编译器说:

  

好的,如果允许从bool到a的隐式转换   boolean_operator,反之亦然,可能会发生一些不好的事情。所以不要   允许那些隐式转换。

您没有告诉编译器(或我们)为什么这些隐式转换是危险的。你只是说他们