【问题标题】:C++20 concept that supposedly depends on itself据称依赖于自身的 C++20 概念
【发布时间】:2021-12-20 07:31:00
【问题描述】:

在我的世界里,StrictNodeType 应该是定义 PredContainer 和 SuccContainer 类型的任何东西,所以我写了

  template<typename N>
  concept StrictNodeType = requires {
    typename N::PredContainer;
    typename N::SuccContainer;
  };

但是,GCC-11.2 给了我以下错误:

error: satisfaction of atomic constraint 'requires{typename N::PredContainer;typename N::SuccContainer;} [with N = typename std::remove_cvref<_Tp>::type::Node]' depends on itself
  164 |   concept StrictNodeType = requires {
      |                            ^~~~~~~~~~
  165 |     typename N::PredContainer;
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~
  166 |     typename N::SuccContainer;something;
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  167 | };

这怎么可能?为什么 GCC 不能简单地检查给定类型并检查它是否提供了请求的子类型?

这是一个最小的破坏示例:

#include <type_traits>

template<typename N>
concept StrictNodeType = requires {
    typename N::something;
};

template<StrictNodeType N> using Int = int; 

template<int>
struct X {using type = Int<X>; };

using ThisBreaks = Int<X<0>>;

【问题讨论】:

  • 没有一个最小的例子,这个问题几乎没有用,因为很难猜出你没有提供的代码。
  • GCC 11.2 compiles this code without error。你能在edit这个问题中加入minimal reproducible example吗?
  • 好吧,我的意思是,不应该有 任何代码 会产生此错误,因为无论其他代码如何,StrictNodeType 不会 依赖于自己。
  • @igel: "不管其余的代码" 很明显这很重要,因为你是唯一得到错误的人。
  • 部分错误被截断。另外,即使不是因为这个错误,代码仍然是无效的,因为这个概念不会被满足。

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


【解决方案1】:

似乎存在一个无限递归问题,它比没有它时更能限制一个概念。我做了一些更改以更直接地解决这个问题:

#include <type_traits>

template<typename N>
concept StrictNodeType = requires {
    typename N::something;
};

#if 1
template<StrictNodeType N> using Int = int; 
#else
template<typename N> using Int = int; 
#endif

template<int>
struct X { using something = Int<X<0>>; };

using ThisBreaks=Int<X<0>>;

ThisBreaks foo()
{
    return ThisBreaks{};
}

这会产生以下错误:

<source>:15:37: error: template constraint failure for 'template<class N>  requires  StrictNodeType<N> using Int = int'
   15 | struct X { using something = Int<X<0>>; };
      |                                     ^~
<source>:15:37: note: constraints not satisfied
<source>: In substitution of 'template<class N>  requires  StrictNodeType<N> using Int = int [with N = X<0>]':
<source>:15:37:   required from here
<source>:4:9:   required for the satisfaction of 'StrictNodeType<N>' [with N = X<0>]
<source>:4:26:   in requirements  [with N = X<0>]
<source>:5:14: note: the required type 'typename N::something' is invalid
    5 |     typename N::something;
      |     ~~~~~~~~~^~~~~~~~~~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
<source>:17:25: error: template constraint failure for 'template<class N>  requires  StrictNodeType<N> using Int = int'
   17 | using ThisBreaks=Int<X<0>>;
      |                         ^~
<source>:17:25: note: constraints not satisfied
<source>: In substitution of 'template<class N>  requires  StrictNodeType<N> using Int = int [with N = X<0>]':
<source>:17:25:   required from here
<source>:4:9:   required for the satisfaction of 'StrictNodeType<N>' [with N = X<0>]
<source>:4:26:   in requirements  [with N = X<0>]
<source>:5:14: note: the required type 'typename N::something' is invalid
    5 |     typename N::something;
      |     ~~~~~~~~~^~~~~~~~~~~~~
<source>:19:1: error: 'ThisBreaks' does not name a type
   19 | ThisBreaks foo()
      | ^~~~~~~~~~
Compiler returned: 1

将#if 1 更改为#if 0 可以正常编译,只有Concept 对象可以无限递归。

(在这里玩一下:https://godbolt.org/z/56Yd7W3sf)

【讨论】:

  • 这也很奇怪 - 如果我们添加 -fconcepts-diagnostics-depth=200 那么错误是 &lt;source&gt;:5:14: error: no type named 'something' in 'struct X&lt;0&gt;' 这似乎与代码相矛盾。但我想人们必须明白这是相关的错误:&lt;source&gt;:5:14: error: invalid use of incomplete type 'struct X&lt;0&gt;'
  • @igel 通过设置 depth=200,就好像任何 201 或更大的深度都不存在。所以没有报告的类型 X。
  • 原谅我的无知,我在错误消息中找不到任何关于 X 的信息 oO
  • X 表示 X 作为第 201 级递归,您告诉编译器不要再深入了,所以任何本来可以创建的东西都不存在。看:godbolt.org/z/oqhrjKcvf:```template struct UP { UP() {UP x;} };模板 结构 UP { };上 x; ``` 我已经设置了 -ftemplate-depth=200 所以它找不到 UP 来停止递归。就编译器而言,深度 200 的 UP 不存在。
  • 好的,但我说的是-fconcepts-diagnostics-depth=200 而不是-ftemplate-depth=200。我想我明白了有限模板深度递归的想法,尽管我仍然发现错误消息 no type named 'something' in 'struct X&lt;0&gt; 令人困惑,并且宁愿看到 template instantiation depth exceeds maximum 就像在你的上帝螺栓中一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-12
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多