Passing a pointer to base_all<U...>
merely requires the existence of a declaration of base_all<U...>
. Without attempting the to access the definition, the compiler won’t detect that the type is actually ill-defined. One approach to mitigate that problem would be to use an argument which requires a definition of base_all<U...>
, e.g.:
template< class ...T> struct base_all
: id<T> ...
{
typedef int type;
};
// ...
template< class ... U>
static constexpr bool test(typename base_all<U...>::type) noexcept
{
return true;
}
Although the above answers the question, it fail to compile: the multiple inheritance created isn’t in a suitable context to be considered for SFINAE. I don’t think you can leverage the rule on not allowing the same base inherited from twice. The relevant test can be implemented differently, though:
#include <type_traits>
template <typename...>
struct is_one_of;
template <typename F>
struct is_one_of<F>
{
static constexpr bool value = false;
};
template <typename F, typename S, typename... T>
struct is_one_of<F, S, T...>
{
static constexpr bool value = std::is_same<F, S>::value
|| is_one_of<F, T...>::value;
};
template <typename...>
struct is_unique;
template <>
struct is_unique<> {
static constexpr bool value = true;
};
template<typename F, typename... T>
struct is_unique<F, T...>
{
static constexpr bool value = is_unique<T...>::value
&& !is_one_of<F, T...>::value;
};
int main()
{
constexpr bool b = is_unique<int, float, double>::value;
constexpr bool c = is_unique< int, char, int>::value;
static_assert( b == true && c == false , "!");
}