显式强制转换,直接初始化和复制初始化之间的行为不同 [英] Different behavior among explicit cast, direct initialization and copy initialization

查看:113
本文介绍了显式强制转换,直接初始化和复制初始化之间的行为不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类C,它具有任何类型的转换运算符.在示例中,我尝试以三种不同的方式将其实例转换为std::string:static_caststd::string的构造函数并分配给std::string.但是,只有最后一个会编译,而其他会引发构造函数模棱两可的错误.

I have a class C which has a casting operator to anything. In the example I tried to cast an instance of it to std::string in three different ways: static_cast, constructor of std::string and assigning to std::string. However, only the last one compiles, while the others raise an error of ambiguous constructor.

错误的原因很明显:有很多方法可以将C转换为std::string的构造函数可以接受的东西.但是,这两种情况有什么区别?为什么强制转换运算符在这里但不在那里按预期工作?

The reason of the error is clear enough: there are many ways to convert C to something which the constructor of std::string can accept. But what is the difference between these cases? Why cast operator works as intended here but not there?

struct C {
    template<typename T>
    operator T() const {
        return T{};
    }
};

int main() {
    C c;

    cout << static_cast<string>(c) << endl; // compile error
    string bad(c); // compile error
    string ok = c; // compiles successfully
}

UPD :正如bolov在评论中提到的,此问题不会在C ++ 17中重现.我使用g ++-5和clang-3.8以及-std = c ++ 11和-std = c ++ 14对其进行了测试,它显示了所描述的错误.

UPD: as bolov mentioned in comments, this issue doesn't reproduce with C++17. I tested it with g++-5 and clang-3.8 with -std=c++11 and -std=c++14, and it shows the described errors.

推荐答案

在C ++ 17之前

static_cast<string>(c)string bad(c)执行直接初始化,然后

检查T的构造函数,并通过重载分辨率选择最佳匹配.然后调用构造函数以初始化对象.

the constructors of T are examined and the best match is selected by overload resolution. The constructor is then called to initialize the object.

正如您所说,std::string的所有可能的构造函数都会被检查,并且C可以转换为所需的任何内容,然后造成歧义.

As you said, all the possible constructors of std::string are examined and C can be converted to anything required, then causes ambiguity.

string ok = c执行复制初始化(请注意,这不是分配),然后

string ok = c performs copy initialization (note it's not assignment), then

如果T是类类型,并且other类型的cv不合格版本不是T或从T派生,或者T是非类类型,但是other的类型是类类型,用户定义的转换序列可以从other的类型转换为T(如果T是类类型和转换,则可以转换为从T派生的类型)功能可用)进行检查,并通过过载分辨率选择最佳的.

If T is a class type, and the cv-unqualified version of the type of other is not T or derived from T, or if T is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other to T (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution.

这意味着将检查从Cstd::string的转换,并将其用于此处的初始化.

That means the conversion from C to std::string is examined, and used for the initialization here.

在C ++ 17之后

从C ++ 17开始,用于直接初始化

Since C++17 for direct initlizatioin,

如果初始化程序是一个prvalue表达式,其cv不合格类型与T是同一类,则初始化程序表达式本身(而不是从其实例化的)用于初始化目标对象:请参见复制省略(自C ++ 17起)

if the initializer is a prvalue expression whose cv-unqualified type is the same class as T, the initializer expression itself, rather that a temporary materialized from it, is used to initialize the destination object: see copy elision (since C++17)

这意味着将执行从Cstd::string的转换并将其用于初始化,然后模糊性消失并且代码运行良好.

That means the conversion from C to std::string is perferred and used for the initialization, then the ambiguity disappears and the code works well.

实时

这篇关于显式强制转换,直接初始化和复制初始化之间的行为不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆