std::variant 和不明确的初始化

use*_*538 10 c++ std language-lawyer c++17

考虑以下代码:

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

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

int main()
{
    fnc(42.3); // error
}
Run Code Online (Sandbox Code Playgroud)

由于对 的调用不明确,它会给出错误fnc
但是,如果我们编写下面的代码:

std::variant<int, long double> v{42.3};
std::cout << v.index();
Run Code Online (Sandbox Code Playgroud)

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

康桓瑋*_*康桓瑋 6

在P0608之前,也存在由于可以转换为or而variant<int, long double> v{42.3} 产生歧义的问题42.3intlong double

P0608 改变了构造函数的行为variant

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

  • Tj是一个按如下方式确定的类型:FUN(Ti)为每个替代类型构建一个虚函数Ti ,该函数Ti x[] = {std::forward<T>(t)};对于某些发明变量来说格式良好x,并且如果Ticv boolremove_cvref_t<T>则为 bool。FUN(Ti) 重载决策为表达式选择的 重载FUN(std::forward<T>(t))定义了替代项Tj,即构造后所包含值的类型。

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

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

由于only#2格式良好,因此可以variant成功推导所包含值类型的类型long double