使用SFINAE检测相同的类继承

pol*_*.ph 4 c++ decltype sfinae template-meta-programming c++11

我正在尝试编写一个元函数来检查作为可变参数模板参数传递的所有类型是否都是不同的.似乎最高效的方法是从一组类继承并检测是否存在错误.

问题是编译在以下代码中失败,而我希望SFINAE能够工作.

编辑.问题不是"如何编写该元函数",而是"如何false_type在发生时捕获双重继承错误和输出".AFAIK,只有SFINAE才有可能.


template <typename T>
struct dummy {};

// error: duplicate base type ‘dummy<int>’ invalid
template <typename T, typename U>
struct fail : dummy<T>, dummy<U> {};

template <typename T>
true_type test(fail<T, T> a = fail<T, T>());

false_type test(...);

int main() {
    cout << decltype(test<int>())::value << endl;
}
Run Code Online (Sandbox Code Playgroud)

现场版.


编辑.以前我曾尝试使用特殊化失败来做到这一点,但它在使用相同的编译错误时也无法正常工作.

template <typename T>
struct dummy {};

template <typename T, typename U>
struct fail : dummy<T>, dummy<U>, true_type {};

template <typename T, typename U = void>
struct test : false_type {};

template <typename T>
struct test<T, typename enable_if<fail<T, T>::value, void>::type> : true_type {};
Run Code Online (Sandbox Code Playgroud)

现场版.

eca*_*mur 6

您无法使用SFINAE捕获重复继承,因为在14.8.2p8 [temp.deduct]下,它不是列出失败的原因之一.同样地,这是因为错误发生在模板推导的"直接上下文"之外,因为它是你的实例化的错误struct fail.

然而,有一种非常类似的技术适用于您的情况,即检测从派生类到多个基类的模糊转换.显然,不能直接从单个派生类继承不明确的基类,但它可以在线性链中继承它们:

C<> A<int>
|  /
C<int> A<char>
|     /
C<char, int> A<int>
|           /
C<int, char, int>
Run Code Online (Sandbox Code Playgroud)

现在从转换C<int, char, int>A<int>将是含糊的,模棱两可的转换 14.8.2p8下上市,我们可以使用SFINAE检测到它:

#include <type_traits>

template<class> struct A {};
template<class... Ts> struct C;
template<> struct C<> {};
template<class T, class... Ts> struct C<T, Ts...>: A<T>, C<Ts...> {};
template<class... Ts> void f(A<Ts>...);
template<class... Ts> std::false_type g(...);
template<class... Ts> decltype(f((A<Ts>(), C<Ts...>())...), std::true_type()) g(int);
template<class... Ts> using distinct = decltype(g<Ts...>(0));

static_assert(distinct<int, char, float>::value, "!!");
static_assert(!distinct<int, char, int>::value, "!!");
Run Code Online (Sandbox Code Playgroud)