I have a templated class A
and a templated function f
which returns A
objects. I want f<T>
to be a friend of A<T>
and still be constexpr
template <typename T>
class A;
template <typename T>
constexpr A<T> f();
//f<T> is a friend of A<T>
template <typename T>
class A {
friend /* constexpr? */ A f<T>();
constexpr A() {}
};
template <typename T>
constexpr A<T> f() { return {}; }
int main() {
constexpr auto a = f<void>();
}
I can't get clang and gcc to agree on what's right here. If I don't put constexpr
in the friend declaration, gcc works fine but clang won't compile it, erroring with:
main.cpp:18:18: error: constexpr variable 'a' must be initialized by a constant expression
constexpr auto a = f<void>();
^ ~~~~~~~~~
main.cpp:18:23: note: non-constexpr function 'f<void>' cannot be used in a constant expression
constexpr auto a = f<void>();
^
main.cpp:9:12: note: declared here
friend A f<T>();
If I mark it as constexpr
in the friend declaration, clang compiles fine but gcc gives me the error:
main.cpp:9:27: error: 'constexpr' is not allowed in declaration of friend template specialization 'A<T> f<T>()'
friend constexpr A f<T>();
How can I make everyone happy?
int main() { constexpr auto a = f<void>(); }
This specializes the function template f
as the function f<void>()
; during the specialization of f
, the compiler also attempts to instantiate A<void>
, which in turn declares the specialization friend f<void>()
.
These two declarations must match for constexpr
:
[dcl.constexpr] / 1
[...] If any declaration of a function or function template has a
constexpr
specifier, then all its declarations shall contain theconstexpr
specifier. [Note: An explicit specialization can differ from the template declaration with respect to theconstexpr
specifier. —end note]
Clang should probably be erroring out earlier when you omit constexpr
in the friend
declaration rather than stamping out what appears to be a non-constexpr
function, but at least it accepts the correct syntax.
Gcc shouldn't allow the version missing constexpr
, and gives an error when you do provide constexpr
due to a bug. This has since been fixed in the trunk and I can confirm it works now, although it still does not provide an error when constexpr
is missing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With