struct Outer
{
explicit constexpr Outer(int ii) : n(ii) {}
explicit constexpr Outer(double dd) : n(dd) {}
explicit constexpr Outer(double*) : Outer(3.1415926) {}
explicit constexpr Outer(int*): Outer(42) {}
template <typename R>
static
constexpr
Outer meow(R* r = nullptr) { return Outer(r); }
int as_i() const { return n.i; }
double as_d() const { return n.d; }
union Inner
{
int i;
double d;
constexpr Inner(int ii) : i(ii) {}
constexpr Inner(double dd) : d(dd) {}
~Inner () {}; // non-trivial destructor
};
Inner n;
};
//#include <type_traits>
//static_assert(std::is_literal_type_v<Outer>); // failed by both GCC and clang
int main(int argc, char**)
{
auto const o = Outer::meow(&argc);
return o.as_i();
}
The above code is compiled by GCC 12.1 but rejected by clang 14.0.0
https://godbolt.org/z/o6Tvrrdsv
clang (correctly, in my opinion) complains that
<source>:12:11: error: constexpr function's return type 'Outer' is not a literal type
Outer meow(R* r = nullptr) { return Outer(r); }
^
<source>:28:11: note: 'Outer' is not literal because it has data member 'n' of non-literal type 'Outer::Inner'
Inner n;
^
<source>:36:24: error: no matching function for call to 'meow'
auto const o = Outer::meow(&argc);
^~~~~~~~~~~
<source>:12:11: note: candidate template ignored: substitution failure [with R = int]
Outer meow(R* r = nullptr) { return Outer(r); }
^
Even though o
is merely const, not constexpr
, shouldn't this be an error? meow
is trying to do something which shouoldn't be allowed.
(If I make o
into constexpr
, then GCC complains that Outer
has a non-trivial destructor.)
Yes, the return type of a constexpr
function must be a literal type and Outer
is not. If a function definition doesn't satisfy the constexpr
requirements, the program would be ill-formed.
However, you have a function template here. constexpr
on a function template is allowed as long as there is at least one specialization which satisfies the requirements of a constexpr
function. However, if this requirement is not fulfilled, the program isn't ill-formed . It is ill-formed, no diagnostic required (IFNDR).
There is no specialization here satisfying the requirements because you always have the Outer
return type and so the program is IFNDR.
Both compilers are correct. They do not need to diagnose that the program is ill-formed.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.