I need to make a template specialization which distinguish between a template class with (only) value parameters like the following:
template<auto ... __vz>
struct values{};
and a template class with (only) reference parameters like the following:
template<auto& ... __lvz>
struct lvalues{};
But with following specialization I was not successful:
template<typename>
struct is_values{
static constexpr bool value = false;
};
template<template<auto ...>class __m, auto ... __vz>
struct is_values<__m<__vz ...> >{
static constexpr bool value = true;
};
template<typename>
struct is_lvalues{
static constexpr bool value = false;
};
template<template<auto& ...>class __m, auto& ... __vz>
struct is_lvalues<__m<__vz ...> >{
static constexpr bool value = true;
};
When they are tested like the following:
const int a = 1;
const int b = 2;
const int c = 3;
int main()
{
std::cout << is_values<lvalues<a,b,c> >::value <<std::endl; // wrong result
std::cout << is_lvalues<values<1,2,3> >::value <<std::endl; // causes error
}
One of them gives a wrong result and one gives the following error:
test.cpp: In instantiation of ‘struct is_lvalues<values<1, 2, 3> >’:
test.cpp:51:41: required from here
test.cpp:32:34: error: initializing ‘int&’ with ‘int’ in converted constant expression does not bind directly
32 | struct is_lvalues<__m<__vz ...> >{
| ^
test.cpp:32:34: error: could not convert ‘1’ from ‘int’ to ‘int&’
test.cpp:32:34: error: initializing ‘int&’ with ‘int’ in converted constant expression does not bind directly
test.cpp:32:34: error: could not convert ‘2’ from ‘int’ to ‘int&’
test.cpp:32:34: error: initializing ‘int&’ with ‘int’ in converted constant expression does not bind directly
test.cpp:32:34: error: could not convert ‘3’ from ‘int’ to ‘int&’
test.cpp:33:24: error: initializing ‘int&’ with ‘int’ in converted constant expression does not bind directly
33 | static constexpr bool value = true;
| ^~~~~
test.cpp:33:24: error: could not convert ‘1’ from ‘int’ to ‘int&’
test.cpp:33:24: error: initializing ‘int&’ with ‘int’ in converted constant expression does not bind directly
test.cpp:33:24: error: could not convert ‘2’ from ‘int’ to ‘int&’
test.cpp:33:24: error: initializing ‘int&’ with ‘int’ in converted constant expression does not bind directly
test.cpp:33:24: error: could not convert ‘3’ from ‘int’ to ‘int&’
test.cpp: In function ‘int main()’:
test.cpp:51:43: error: ‘value’ is not a member of ‘is_lvalues<values<1, 2, 3> >’
51 | std::cout << is_lvalues<values<1,2,3> >::value <<std::endl; // causes error
| ^~~~~
make: *** [src/subdir.mk:20: src/test.o] Error 1
"make all" terminated with exit code 2. Build might be incomplete.
12:14:37 Build Failed. 14 errors, 0 warnings. (took 677ms)
So far I was only successful with the following specializations:
template<auto ... __vz>
struct is_values<values<__vz ...> >{
static constexpr bool value = true;
};
template<auto& ... __vz>
struct is_lvalues<lvalues<__vz ...> >{
static constexpr bool value = true;
};
But these are not desired because they only detect the types resulted from values and lvalues not any other similar template with different name.
So what is the right specialization?