Consider the following program:
template<typename T>
constexpr int f()
{
T{}.i; // error if instantiated with [T = double]
return 42;
}
constexpr void g(char);
using U = decltype( g( {f<double>()} ) );
To my understanding, the last line is an error because the call to f<double>()
is within a brace initializer, and even though f<T>
returns an int
, the value of the returned int
is needed to decide if it can be narrowed to a char
as expected by g
. This requires the definition of f
to be instantiated with double
, which causes an error. Both gcc and clang reject this code.
However, if the definition of g
is changed to accept an int
parameter:
constexpr void g(int);
then it seems that there is no need to instantiate the definition of f
, since the narrowing conversion must succeed. Indeed, gcc accepts this, but clang still instantiates f
with double
and rejects the code. Additionally, if f
is only declared, but not defined, clang accepts the code, which implies that the definition is not needed, and shouldn't be instantiated.
Is my reasoning correct, and this is a clang bug, or is instantiation required, and this is actually a gcc bug?