There is a nice question (Which substitution failures are not allowed in requires clauses?) proposing the next problem.
One needs to write a compile-time function template<typename... Ts> constexpr bool allTypesUnique()
that will return true
if all argument types are unique, and false
otherwise. And the restriction is not to compare the argument types pairwise. Unfortunately, the answer only explains why such function cannot be implemented with some particular approach.
I think the solution can be achieved using multiple inheritance. The idea is to make a class inherited from a number of classes: one for each type T
in Ts
. And each such class defines a virtual function with a signature depending on T
. If some T
is found more than once in Ts
then function f
in a child class will override the function in a base class and it can be detected:
template<typename> struct A{};
template<typename T, typename... Ts>
struct B : B<Ts...> {
using B<Ts...>::f;
constexpr virtual void f(A<T>, bool & unique) { if( ++count > 1 ) unique = false; }
int count = 0;
};
template<typename T>
struct B<T> {
constexpr virtual void f(A<T>, bool & unique) { if( ++count > 1 ) unique = false; }
int count = 0;
};
template<typename... Ts>
constexpr bool allTypesUnique() {
B<Ts...> b;
bool res = true;
( b.f( A<Ts>{}, res ), ... );
return res;
}
int main() {
static_assert( allTypesUnique<void>() );
static_assert( allTypesUnique<void, int&>() );
static_assert( !allTypesUnique<int&, int&>() );
static_assert( allTypesUnique<char, short, int>() );
static_assert( !allTypesUnique<char, short, char>() );
}
Demo: https://gcc.godbolt.org/z/8jhnE7P11
Just curious, is the solution correct and is there a simpler solution for this problem?