简体   繁体   English

据说依赖于自身的 C++20 概念

[英]C++20 concept that supposedly depends on itself

In my world, a StrictNodeType should be anything that defines the types PredContainer and SuccContainer , so I wrote在我的世界中, StrictNodeType应该是定义PredContainerSuccContainer类型的任何东西,所以我写了

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

However, GCC-11.2 gives me the following error:但是,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 | };

How is that possible?这怎么可能? Why can't GCC simply inspect the given type and check if it provides the requested subtypes?为什么 GCC 不能简单地检查给定的类型并检查它是否提供了请求的子类型?

Here's a minimum breaking example:这是一个最小的破坏示例:

#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>>;

It seems there is an infinite recursion issue that constrains a concept more than it would be without it.似乎有一个无限递归问题比没有它更能限制一个概念。 I made a few changes to get more directly at the issue:我做了一些更改以更直接地解决问题:

#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{};
}

This yields the following error:这会产生以下错误:

<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

Changing #if 1 to #if 0 compiles fine, only the Concept objects to the infinite recursion.#if 1更改为#if 0编译正常,只有 Concept 对象进行无限递归。

(Play with it here: https://godbolt.org/z/56Yd7W3sf ) (在这里玩: https : //godbolt.org/z/56Yd7W3sf

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM