std::variant 和模棱两可的初始化

std::variant and ambiguous initialization

考虑以下代码:

void fnc(int)
{
    std::cout << "int";
}

void fnc(long double)
{
    std::cout << "long double";
}

int main()
{
    fnc(42.3); // error
}

由于对 fnc.
的模糊调用,它给出了一个错误 但是,如果我们写下一段代码:

std::variant<int, long double> v{42.3};
std::cout << v.index();

输出为1,表明选择了double->long double转换。 据我所知,std::variant 遵循关于转换等级的 C++ 规则,但这个例子显示了不同之处。对这种行为有什么解释吗?

P0608, variant<int, long double> v{42.3} also has the ambiguous issue之前,因为42.3可以转换为intlong double

P0608 已更改 the behavior of variant's constructors:

template<class T> constexpr variant(T&& t) noexcept(see below);

  • Let Tj be a type that is determined as follows: build an imaginary function FUN(Ti) for each alternative type Ti for which Ti x[] = {std::forward<T>(t)}; is well-formed for some invented variable x and, if Ti is cv bool, remove_cvref_t<T> is bool. The overload FUN(Ti) selected by overload resolution for the expression FUN(std::forward<T>(t)) defines the alternative Tj which is the type of the contained value after construction.

在您的示例中,variant 有两种替代类型:intlong double,因此我们可以构建以下表达式

        int x[] = {std::forward<double>(42.3)}; // #1
long double y[] = {std::forward<double>(42.3)}; // #2

由于only #2 is well-formedvariant成功推导出包含的值类型long double