2

我想要求编译器检查一个元组是否只包含“元类型”。

顺便说一句,我对 C++ 概念完全陌生。

template < typename T >
struct Type {
  using type = T;
};

//! A type can be easily check with a small concept
template < typename T >
concept bool  C_Type = requires {
  typename T::type;
};

//! But how to apply it on a whole tuple?
template < typename T >
void foo(T tuple) {}

int main() {

  constexpr auto  test = std::make_tuple(Type<int>{}, Type<double>{});
  foo(test);
}

所以我想确保序列中的每个类型(我们只说这个例子的 Iterable )都是“元类型”。

如果它可以简化代码,我正在使用 Boost Hana。

目前我什至不确定这是否可能。我希望是的,我想我只需要学习更多元编程的东西。所以我会继续搜索和尝试,但如果有人已经有了答案,谢谢!

4

3 回答 3

3

概念在设计上太弱而无法执行元编程,因此要做到这一点,您需要语言其余部分的“元编程帮助”。我会使用模板专业化将类型分解为模板及其类型参数,然后要求所有这些参数满足C_Type

template <class>
constexpr bool TypeTuple_ = false;
template <template <class...> class Tuple, class... Types>
  requires (C_Type<Types> && ...)
constexpr bool TypeTuple_<Tuple<Types...>> = true;

template <class T>
concept bool TypeTuple = TypeTuple_<T>;

这适用于hana::tuple, 和std::tuple- 任何接受所有类型参数的模板。

于 2017-09-05T23:50:04.140 回答
2

我对概念不太熟悉,但您当然可以通过多种方式使用 Boost.Hana 实现这一点。

通过查看注释,应该注意的是,任何元组类型都可以hana::Sequence按约定变成 a which 也是hana::Searchableand hana::Foldable

这是一个std::tuple用作的示例hana::Searchable

#include <boost/hana.hpp>
#include <boost/hana/ext/std/tuple.hpp>
#include <tuple>
namespace hana = boost::hana;

template < typename T >
concept bool  C_Type = requires {
  typename T::type;
};

auto is_C_Type = hana::overload_linearly([](C_Type const&) { return hana::true_c; },
                                         [](auto const&)   { return hana::false_c; });

template < typename T >
constexpr bool foo(T const& tuple) {
  return hana::all_of(tuple, is_C_Type);
}

int main() {
  constexpr auto  test = std::tuple{hana::type_c<int>, hana::type_c<double>};
  static_assert(foo(test));
}

https://wandbox.org/permlink/YNZDX7uN6mgUdmje

于 2017-09-05T22:35:52.633 回答
1

这是一个如何检查是否tuple仅包含定义 typename 的类型的示例type。这里的技巧是定义一个 tuple 类型,该类型std::pair<std::pair<...std::pair<void, T0>, ...TN>, TM>为 tuple定义一个新类型std::tuple<T0, ..., TN, TM>。这适用于 GCC 7.2。我对如何更干净地结合可变参数约束感兴趣,因为我没有找到任何参考资料。

#include <array>
#include <tuple>

template<typename T>
struct Type {
    using type = T;
};

template<typename Tuple, size_t I = std::tuple_size<Tuple>::value>
struct TupleType {
    using type = std::pair<typename TupleType<Tuple, I - 1>::type,
                           typename std::tuple_element<I - 1, Tuple>::type>;
};

template<typename Tuple>
struct TupleType<Tuple, 0> {
    using type = void;
};

template<typename T>
concept bool C_TupleType = requires {
    typename TupleType<T>::type;
};

void foo(C_TupleType tuple) { }

int main() {
    constexpr auto test = std::make_tuple(Type<int>{}, Type<double>{});
    foo(test);

    // also works on pair and array
    constexpr auto test1 = std::make_pair(Type<int>{}, Type<double>{});
    foo(test1);
    constexpr std::array<Type<int>, 3> test2;
    foo(test2);

    // and of course TupleType is also a meta type
    constexpr std::array<TupleType<std::pair<int, int>>, 13> test3;
    foo(test3);

    return 0;
}
于 2017-09-05T21:21:12.490 回答