你可以static_assert一个元组只有一种满足特定条件的类型吗?

时间:2018-02-26 16:41:26

标签: c++ templates c++17 variadic-templates template-meta-programming

此代码获取满足测试的第一个元组元素(在这种情况下,如果它派生<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <p class="p1">The first paragraph in body.</p> <p class="p1">The second paragraph in body.</p> <p class="p2">The third paragraph in body.</p> <p class="p2">The fourth paragraph in body.</p>)。 我怎样才能static_assert只有一个满足该条件的元素可能存在?(很像C ++ 17的Base如果提供的typename中存在多个元素,则无法编译。)< / p>

std::get<class>

2 个答案:

答案 0 :(得分:1)

这是一种不太优雅,但与C ++ 11兼容的方式。

#include <iostream>
#include <tuple>

struct foo {

};

struct bar : foo {

};

template <std::size_t N, typename... T>
struct check_tuple;

template <std::size_t N, typename First, typename... Rest>
struct check_tuple<N, First, Rest...> : check_tuple<N+std::is_base_of<foo, First>::value , Rest...> {};

template <std::size_t N, typename First>
struct check_tuple<N, First> : check_tuple<N+std::is_base_of<foo, First>::value> {};

template <std::size_t N>
struct check_tuple<N> : std::false_type {};

template <>
struct check_tuple<1> : std::true_type {};

template <typename Types>
struct check_tuple_types;

template <typename... Types>
struct check_tuple_types<std::tuple<Types...>> : check_tuple<0, Types...> {};

int main() {
    std::cout << check_tuple_types<std::tuple<int, long, bar>>::value;
    return 0;
}

答案 1 :(得分:0)

如果我正确理解您和您的代码,那么此专业化适用于类型T0通过您的测试时:

template<template<class...> class Test, class T0, class...Ts>
struct first_pass<Test, std::enable_if_t<Test<T0>::value>, T0, Ts...> {
  using type = T0;
};

所以你找到了一种通过测试的类型,现在你想确保Ts中还没有通过测试的类型?如果是,则可以添加以下实用程序:

template <bool... bs>
struct any_of : public std::false_type {  };

template <bool b, bool... bs>
struct any_of<b, bs...> : 
    public std::conditional_t<b, std::true_type, any_of<bs...>> {  };

然后使用它:

template<template<class...> class Test, class T0, class...Ts>
struct first_pass<Test, std::enable_if_t<Test<T0>::value>, T0, Ts...> {
  static_assert(!any_of<Test<Ts>::value...>::value, 
                "multiple types pass the test");

  using type = T0;
};

另外,我不熟悉C ++ 17,所以请考虑这是一种前C ++ 17方法(使用已有的代码)。