【问题标题】:How to define a recursive concept?如何定义递归概念?
【发布时间】:2019-11-06 13:10:33
【问题描述】:

cppreference.com 声明:

概念不能递归地引用自己

但是我们如何定义一个概念来表示整数或整数向量,或整数向量的向量等。

我可以有这样的东西:

template < typename Type > concept bool IInt0 = std::is_integral_v<Type>;
template < typename Type > concept bool IInt1 = IInt0<Type> || requires(Type tt) { {*std::begin(tt)} -> IInt0; };
template < typename Type > concept bool IInt2 = IInt1<Type> || requires(Type tt) { {*std::begin(tt)} -> IInt1; };

static_assert(IInt2<int>);
static_assert(IInt2<std::vector<int>>);
static_assert(IInt2<std::vector<std::vector<int>>>);

但我想要像 IIntX 这样的东西,这意味着任何 N 的 IIntN

有可能吗?

【问题讨论】:

  • 我很好奇你想把这个概念应用到什么代码上。您如何编写可以以相同方式操作整数和向量的代码,而不使用一堆 if constexpr 或等效代码,这最终会使概念的全部意义变得毫无意义?确实,您应该非常仔细地查看|| 在概念中的使用
  • @NicolBolas || 很难支持无限嵌套容器。
  • @Yakk-AdamNevraumont 我认为指针更多......你的算法对intvector&lt;vector&lt;vector&lt;int&gt;&gt;&gt;都有意义吗?
  • @Barry 这不难吗?我的意思是,“增加每个 int”对两者都有意义。 monad 的自动拆箱(或对其内容进行操作)并不疯狂,即使它需要任意下降。在我看来,自动装箱疯狂;反之亦然,尤其是在单个操作上,很好。
  • @Yakk-AdamNevraumont:也许更合理的用例是一个函数的概念,它采用一系列范围并压平范围。从逻辑上讲,这样的东西应该能够任意地沿着每个内部范围的value_type 向下隧道,直到它找到一个非范围的东西,所有不同的范围都必须在相同的value_type 上达成一致。但没有办法在概念中轻松表达这一点。或者至少,不是没有去可怕的、非概念的东西。

标签: c++ recursion c++20 c++-concepts


【解决方案1】:

概念总是可以遵循类型特征:

template <typename T> concept C = some_trait<T>::value;

并且该特征可以是递归的:

template <typename T>
struct some_trait : std::false_type { };

template <std::Integral T>
struct some_trait<T> : std::true_type { };

template <typename T, typename A>
struct some_trait<std::vector<T, A>> : some_trait<T> { };

如果你不只是指vector,那么最后的部分特化可以概括为:

template <std::Range R>
struct some_trait<R> : some_trait<std::range_value_t<R>> { };

【讨论】:

    猜你喜欢
    • 2016-07-17
    • 2018-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多