https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113007

--- Comment #4 from Pavel Novikov <paul.skeptic at yandex dot ru> ---
Interesting. Thank you for explanation.

Indeed the standard says all over that narrowing conversion in initialization
is prohibited, though this code compiles:

    int i = 42;
    bool b[] = {i}; // narrowing
    int64_t i64[] = {i};
    double d[] = {i}; // narrowing*

(*putting aside that any `int` can be _exactly_ represented by a double
precision floating point value)

As an approximation for `T x[] = {t}` requirement I came up with this code:

    template<typename T, typename U>
    std::enable_if_t<sizeof(decltype(T{std::declval<U>()}))>
    test() {}

and indeed it fails to compile when narrwoing conversion is required, i.e.

    test<bool, int>(); // error: narrowing
    test<int64_t, int>();
    test<double, int>(); // error: narrowing

So turning

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

into code using the approximation above we have the following code

    template<typename T, typename U>
    std::enable_if_t<sizeof(decltype(T{std::declval<U>()}))>
    F(U) {}

    F<bool>(42); // error: deduction/substitution failed due to narrowing
    F<int64_t>(42);
    F<double>(42); // error: deduction/substitution failed due to narrowing

And if we consider `F<T_j>()` functions as an overload set, then indeed only
`F<int64_t>()` is well formed considering (non)narrowing requirement and is
ultimately selected.
(See https://godbolt.org/z/sxof45Eeh)

Did I get it right?

Reply via email to