I want to implement a has_no_duplicates<...>
type trait that evaluates to std::true_type
if the passed variadic type list has no duplicate types.
static_assert(has_no_duplicates<int, float>{}, "");
static_assert(!has_no_duplicates<float, float>{}, "");
Let's assume, for the scope of this question, that I want to do that using multiple inheritance.
When a class inherits from the same type more than once, an error occurs.
template<class T>
struct type { };
template<class... Ts>
struct dup_helper : type<Ts>... { };
// No errors, compiles properly.
dup_helper<int, float> ok{};
// Compile-time error:
// base class 'type<float>' specified more than once as a direct base class
dup_helper<float, float> error{};
I assumed I could've used void_t
to "detect" this error, but I couldn't implement a working solution following the code samples from cppreference.
This is what I tried:
template<class, class = void>
struct is_valid
: std::false_type { };
// First try:
template<class T>
struct is_valid<T, std::void_t<decltype(T{})>>
: std::true_type { };
// Second try:
template<class T>
struct is_valid<T, std::void_t<T>>
: std::true_type { };
For my third try, I tried delaying the expansion of dup_helper<...>
using a wrapper class that took dup_helper
as a template template parameter, like wrapper<dup_helper, ...>
and expanded it inside of void_t
.
Unfortunately, all my tries resulted in the aforementioned error always preventing compilation.
I assume this type of error is not detectable as a "substitution failure", but I'd like confirmation.
Is this kind of error actually impossible to detect using void_t
? (Will it always result in a compilation failure?)
Is there a way to detect it without causing compilation to fail? (Or a non-void_t
workaround that still makes use of the "multiple inheritance trick")?