In conjunction with the similar answers provided by @TedLyngmo (https://stackoverflow.com/a/79464046/28414083) and @Jarod42 (https://stackoverflow.com/a/79464150/28414083), the accepted form of solution for the specific question asked would be:
#include <type_traits>
template <class... Types>
struct acceptor {
template <auto... Values>
requires std::conjunction_v<std::is_same<Types, decltype(Values)>...>
static inline void accept(void) {
// ...
}
};
as this compiles in GCC. Unfortunately, this obviously destroys an IDE's ability to use any kind of "intellisense". It also requires you to specify the values, even as literals, in their specific types, meaning that the literal 1
, for example, would not work for an input of a long
's corresponding template non-type parameter as the 1
literal is considered an int
by the compiler. This could be beaten by changing std::is_same_v
to std::is_trivially_constructible_v
in the requirement clause or similar but it's recommended, where possible, to change to something like:
#include <type_traits>
template <class... Types>
struct acceptor {
template <Types... Values>
struct internal {
static inline void accept(void) {
// ...
}
};
};
which has an internal temploid struct that, unlike its internal temploid function counterpart, is able to compile with that template in GCC. This changes the format of the expected use to:
int main(void) {
// allows '1U' specified for 'int'
acceptor<signed char, int, float>::template internal<0, 1U, 0.5f>::accept();
// allows '6' specified for 'unsigned long'
acceptor<unsigned long, double>::template internal<6, -4.6>::accept();
return 0;
}
Tested with gcc
version: Ubuntu 13.2.0-4ubuntu3.