【问题标题】:C++ concepts loopC++ 概念循环
【发布时间】:2018-02-14 04:44:14
【问题描述】:

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

顺便说一句,我对 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。

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

【问题讨论】:

  • 问题是:你会如何使用T tuple?你对它有什么限制?必须是std::tuple 吗?如果是这样,请使用std::tuple_element,如果不定义您自己的特征和约束...请注意std::tuple_element 也处理std::arraystd::pair,所以也许您可以期望任何T 专门使用它foo。否则你可能想尝试使用decltype(std::get&lt;I&gt;(tuple)) 或者你访问你的元组元素。
  • 您显然没有使用当前版本的概念,因为据我所知,concept bool 在该版本的概念中消失了。您具体问的是哪个版本?
  • @Yakk 好吧,我正在阅读 en.cppreference.com/w/cpp/language/constraints 并使用 Gcc 7.1,所以我想成为最后一个。
  • 您可以使用递归“遍历可变参数模板(constexpr 或不)的每个元素,请参阅stackoverflow.com/a/38776200/3426025
  • 当涉及到遵循标准模型的类元组类型时,编程(元或其他)接口由std::tuple_elementstd::tuple_sizestd::get 组成.在这些情况下,使用 indices 是主要的。

标签: c++ metaprogramming c++-concepts boost-hana c++20


【解决方案1】:

概念设计太弱,无法执行元编程,所以要做到这一点,您需要语言其余部分的“元编程帮助”。我会使用模板特化将类型分解为模板及其类型参数,然后要求所有这些参数满足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::tuplestd::tuple - 任何接受所有类型参数的模板。

【讨论】:

  • concept bool 还在 TS 中吗? (因为之前对 OP 的评论而询问)
  • @jasonrice TS 已经发布并且基本上是最终版本,所以是的。不过,它不在 C++20 工作文件中。 Wg21 从 Toronto 的概念语法中删除了“bool”。
【解决方案2】:

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

通过查看 cmets,应该注意的是,任何元组类型都可以制成 hana::Sequence,按照惯例也是 hana::Searchablehana::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

【讨论】:

    【解决方案3】:

    这是一个示例,说明如何检查 tuple 是否仅包含定义类型名 type 的类型。这里的技巧是定义一个元组类型,它为元组std::tuple&lt;T0, ..., TN, TM&gt; 定义一个新类型std::pair&lt;std::pair&lt;...std::pair&lt;void, T0&gt;, ...TN&gt;, TM&gt;。这个works in 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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-17
      • 2014-09-22
      • 2018-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多