Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::variant and ambiguous initialization

Consider the following code:

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

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

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

It gives an error because of an ambiguous call to fnc.
However, if we write the next code:

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

the output is 1, which demonstrates that the double->long double conversion has been chosen. As far as I know, std::variant follows the C++ rules about conversion ranks, but this example shows the difference. Is there any explanation for such a behavior?

like image 932
Denis Avatar asked May 01 '26 09:05

Denis


1 Answers

Before P0608, variant<int, long double> v{42.3} also has the ambiguous issue since 42.3 can be converted to int or long double.

P0608 changed 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.

In your example, the variant has two alternative types: int and long double, so we can build the following expression

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

Since only #2 is well-formed, the variant successfully deduces the type of the contained value type long double.

like image 82
康桓瑋 Avatar answered May 03 '26 00:05

康桓瑋



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!