c++ - 使用 SFINAE 检测同类继承

标签 c++ c++11 template-meta-programming sfinae decltype

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

问题是以下代码编译失败,而我希望 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;
}

Live version here .


编辑。以前我曾尝试在特化失败的情况下执行此操作,但由于相同的编译错误也无法正常工作。

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 {};

Live version here.

最佳答案

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

但是,有一种非常相似的技术适用于您的情况,即检测从派生类到多个基类的不明确转换。显然,不明确的基类不能直接从单个派生类继承,但在线性链中继承它们效果很好:

C<> A<int>
|  /
C<int> A<char>
|     /
C<char, int> A<int>
|           /
C<int, char, int>

现在是从 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, "!!");

关于c++ - 使用 SFINAE 检测同类继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24053998/

相关文章:

C++ Pthread/SFML 音乐 - 错误 AL lib : (EE) alc_cleanup: 1 device not closed

C++ 和 SDL : SDL event repeats endlessly

c++ - 我可以使用基于范围的 for 循环轻松迭代 map 的值吗?

c++ - 检查类型是否具有在 C++ 中定义的 [][]

c++ - 如何在 C++ 中的类体之外定义一个专门的类方法?

c++ - 匹配 {if cond}foo{else}bar{/if} 的正则表达式

c++ - std::function 不允许通过类型

c++ - double /整数模板函数的 vector

c++ - 提取可变参数模板参数包并将其用于类型特征元函数中的另一个可变参数模板?

c++ - SFINAE 组装?