c++ - 你能 static_assert 一个元组只有一种类型满足特定条件吗?

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

此代码获取满足测试的第一个元组元素(在本例中,如果它派生 Base )。 如何 static_assert 认为只有一个满足该条件的元素可能存在?(很像 C++17 的 std::get<class> 如果提供的类型名存在多个元素,则无法编译。)

template<class...>
struct voider { using type = void; };

template<class...Ts>
using void_t = typename voider<Ts...>::type;

template<template<class...> class Test, class Tuple>
struct get_first_pass;

template<template<class...> class Test, class Tuple>
using get_first_pass_t = typename get_first_pass<Test, Tuple>::type;

template<template<class...> class, class, class...>
struct first_pass {};

template<template<class...> class Test, class T0, class...Ts>
struct first_pass<Test, std::enable_if_t<!Test<T0>::value>, T0, Ts...> :
  first_pass<Test, void, Ts...>
{};

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

template<template<class...> class Test, template<class...> class Tuple, class...Ts>
struct get_first_pass<Test, Tuple<Ts...>> : first_pass<Test, void, Ts...>
{};

template<class Base>
struct is_derived_from {
  template<class Derived>
  using test = std::is_base_of<std::decay_t<Base>, std::decay_t<Derived>>;
};

template<class Base, class Tuple>
using get_first_derived =
  get_first_pass_t<is_derived_from<Base>::template test, Tuple>;

template<class Base, class Tuple>
auto get_from_base(Tuple&& tuple)
-> decltype(std::get< get_first_derived<Base, std::decay_t<Tuple>> >(
                                                  std::forward<Tuple>(tuple))) {
  return std::get< get_first_derived<Base, std::decay_t<Tuple>> >(
                                                  std::forward<Tuple>(tuple));
}

最佳答案

不确定您到底想要什么。

但我想,如果你写一个“计数器”如下

// count is derived from
template <typename, typename>
struct count_idf : public std::integral_constant<std::size_t, 0U>
 { };

template <typename Base, template <typename...> class C, typename ... Ts>
struct count_idf<Base, C<Ts...>>
   : public std::integral_constant<std::size_t,
     (is_derived_from<Base>::template test<Ts>::value + ...)>
 { };

您可以在get_from_base()中添加一个static_assert(),如下所示

template<class Base, class Tuple>
auto get_from_base(Tuple&& tuple)
-> decltype(std::get< get_first_derived<Base, std::decay_t<Tuple>> >(
                                                  std::forward<Tuple>(tuple))) {
  static_assert( 1U == count_idf<Base, std::decay_t<Tuple>>{}, 
                 "not one and only one" );
  return std::get< get_first_derived<Base, std::decay_t<Tuple>> >(
                                                  std::forward<Tuple>(tuple));
}

关于c++ - 你能 static_assert 一个元组只有一种类型满足特定条件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48993118/

相关文章:

c++ - 构造函数中的完美转发 (C++17)

C++检测类型是否为字符串对象

c++ - C++ 标准是否对 vector 赋值函数或构造函数有明确的要求?

c++ - 从 QByteArray 以十六进制获取 imei

c++ - 计算当前车辆与前车之间的距离

c++ - 没有特定成员的类型的 SFINAE

c++ - 如何用PCRE2实现/e修饰符?

javascript - 从 mustache 模板 Moodle 3.7 获取数据

java - eclipse 中的字符串

c++ - 模板化运行时检查调用包装器以检测输入参数或返回值中的转换溢出