【问题标题】:Why can't concept refinement use the terse syntax为什么概念细化不能使用简洁的语法
【发布时间】:2019-05-10 03:11:02
【问题描述】:

在提炼概念时,标准中一贯的做法是完整地写出要提炼的概念。例如,在[concepts.integral] 中,SignedIntegral 精炼Integral,如下所示:

template<class T>
  concept Integral = is_integral_v<T>;
template<class T>
  concept SignedIntegral = Integral<T> && is_signed_v<T>;

为什么提炼的概念不能写成:

template<Integral T>
  concept SignedIntegral2 = is_signed_v<T>;

SignedIntegral2 似乎与SignedIntegral 具有相同的明显含义,但它甚至无法在 clang 上编译。这是有原因的吗?

【问题讨论】:

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


    【解决方案1】:

    SignedIntegral2 的声明格式不正确,因为[temp.concept]/4

    一个概念不应有相关的约束。

    了解其中的原因很重要。概念基本上是谓词。他们的工作是接受一系列论据(最常见的是一系列类型)并说出概念是否满足。但是考虑一下这两种不同的实现会给出什么答案:

    • SignedIntegral&lt;int32_t&gt;true
    • SignedIntegral&lt;uint32_t&gt;false
    • SignedIntegral&lt;string&gt;false

    但是:

    • SignedIntegral2&lt;int32_t&gt;true
    • SignedIntegral2&lt;uint32_t&gt;false
    • SignedIntegral2&lt;string&gt; 是...未定义

    概念的全部意义在于约束。建议的替代方案,SignedIntegral2 中的简洁声明 约束 类型参数 TIntegral。由于string 不满足Integral,我们甚至不能问它是否是SignedIntegral2

    换一种说法,SignedIntegral 是一个总函数,而 SignedIntegral2 是一个仅在 Integral 类型上定义的部分函数。如果我们将两者都写成函数,这可能会更清楚:

    template <typename T>
    constexpr bool SignedIntegral() { return Integral<T> && is_signed_v<T>; }
    
    template <Integral T>
    constexpr bool SignedIntegral2() { return is_signed_v<T>; }
    

    重要的是概念始终是全函数,这就是不允许关联约束的原因。


    请注意,出于满足概念的目的,肯定可以将“未定义”视为false 的扩展,但这会给包含规则增加额外的皱纹,而且它肯定是不平凡的实现复杂性。当然,某些未来的标准可能会允许它们。我的水晶球目前在商店里,所以我不能确定。

    【讨论】:

    • 我想我理解你的意思,但is_signed_v 不是针对非算术类型定义为false 而不是“未定义”吗?
    • @HolyBlackCat:是的,但是SignedIntegral2&lt;string&gt; 是未定义的,因为没有非整数类型的SignedIntegral2 的有效实例化。这就是模板约束失败时的含义。现在,如果有一个不受约束的 SignedIntegral2 的单独定义,那么它可以被实例化。从技术上讲,它不会“未定义”;格式不正确
    • @NicolBolas 我没有注意到模板参数是Integral T 而不是typename T。傻我。 ://
    • 这确实是两个独立的问题。 “为什么我们不能有受约束的概念”和“为什么我们不能将概念上的约束定义为连词”。
    • 这个问题在接下来的几年里会看到很多流量。对于任何刚接触概念的人来说,第二个版本无疑看起来很自然。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-23
    • 2021-11-12
    • 1970-01-01
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多