Open user1095108 opened 5 months ago
@llvm/issue-subscribers-clang-frontend
Author: None (user1095108)
Reduced code:
template <typename T> struct S {
static constexpr S val{};
};
constexpr auto foo = S<int>{};
Compiler Explorer: https://godbolt.org/z/Kfdnsh8hn
This is what I had in mind, yes. You need to be able to pass struct S as a template value parameter.
It seem that the title should be changed to
clang does not allow static constexpr data member of the type same as the class template specialization itself
I don't know why GCC allows this. In the declaration of the static data member, the dpp
type itself is incomplete.
The only possibly related wording in the current workding draft is [temp.inst]/3.1:
the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends; and
But since C++17, the declaration of the static data member using constexpr
is also a definition, so I think the definition of an object of an incomplete type (which is ill-formed) is still triggered.
You need to look at the error message:
./../dpp.hpp:703:24: error: constexpr variable cannot have non-literal type 'const dpp<int, short>'
703 | static constexpr dpp max{direct, mmax, emax};
So, clang complains about a non-literal type, but the type is literal. So, at the very least, the error message should be fixed.
The feature could also be interpreted as a gcc extension.
So, clang complains about a non-literal type, but the type is literal.
Note that clang also says:
./dpp.hpp:519:24: note: incomplete type 'const dpp<short, signed char>' is not a literal type
Looking at the definition of literal type (cppreference, [basic.types.general]/10)... it appears to me that there's no well-defined answer to the question whether an incomplete class type is a literal type. (But an incomplete enumeration type is definitely a literal type because it's a scalar type.)
Perhaps the error message should be changed to something like "constexpr variable cannot have incomplete (class) type"?
As you noted, there is ambiguity whether an incomplete class type is a literal type. Some folks at gcc seem to think that it can be. Maybe you need to look at this from a different perspective. Making something an error effectively prohibits certain programming patterns.
If I change the definitions from static constexpr
to static inline
, clang will accept the code. The change is more or less cosmetic and both times the type is incomplete.
For example, a data member:
https://wandbox.org/permlink/zVXns995f9IGBBAv
gcc compiles example without issue.