Consider the following code:
struct wrapper {
int& ref;
constexpr wrapper(int& ref) : ref(ref) {}
};
template <auto&& X>
void fun1() {}
template <wrapper X>
void fun2() {
fun1<X>();
}
int main() {
static int val = 22;
fun2<val>();
}
fun2<X>() takes in a class as non-type template parameter while fun1<X>() takes in a forwarding reference to any object passed to it.
The above fails to compile in GCC but compiles just fine in Clang.
Which compiler is correct here? Is this supposed to be a bug in either of the two compilers?
I tried to change template <wrapper X> to template <const wrapper& X>, but to no avail, as it fails on both GCC and Clang.
>Solution :
Your code is valid. This is possibly a GCC bug:
For a non-type template-parameter of reference or pointer type, or for each non-static data member of reference or pointer type in a non-type template-parameter of class type or subobject thereof, the reference or pointer value shall not refer to or be the address of (respectively):
- a temporary object ([class.temporary]),
- a string literal object ([lex.string]),
- the result of a
typeidexpression ([expr.typeid]),- a predefined
__func__variable ([dcl.fct.def.general]), or- a subobject ([intro.object]) of one of the above.
The reference auto&& X refers to an object wrapper X that is none of those, so it should be a valid template argument.