【发布时间】:2022-12-14 07:29:54
【问题描述】:
在定义 c++20 概念以检查是否通过调用约束函数满足要求时,g++ 和 clang 中的行为不同。如果检查函数无效,g++ 接受一个类型,clang 则相反:
// constrained function
template <class T>
constexpr void foo1(const T& type)
requires requires { type.foo(); }{}
// function with required expression in the body
template <class T>
constexpr auto foo2(const T& type)
{ type.foo(); } // (x)
// check for valid expression foo1
template <class T>
concept checkFoo1 = requires(T t) { foo1(t); };
// check for valid expression foo2
template <class T>
concept checkFoo2 = requires(T t) { foo2(t); };
检查没有 foo() 作为成员的类型的概念会给出不一致的行为:
struct Test
{
// void foo() const {}
};
int main()
{
static_assert(checkFoo1<Test>); // (1)
static_assert(checkFoo2<Test>); // (2)
static_assert(!checkFoo1<Test>); // (3)
static_assert(!checkFoo2<Test>); // (4)
}
在 clang-15 中:(1),(2): static assertion, (3),(4): succeed,另外 (x) 中的错误,参见https://godbolt.org/z/zh18rcKz7
g++-12: (1),(4): static assertion, (2),(3): succeed, additionally an error in (x), see https://godbolt.org/z/qMsa59nd3
在所有情况下,概念检查都不会在静态断言的错误消息中说明失败的原因,即未找到成员函数.foo()。它只是告诉您对foo1() 或foo2() 的调用无效。
我的问题是:
- 什么是正确的行为,为什么?
- 如何通过约束函数检查概念,以及有关为什么调用
foo1()或foo2()无效以及未满足这些函数的约束的详细信息。
当然,我可以直接检查成员函数foo() 是否存在。但这只是一个例子。目标是通过对受限函数的递归函数调用来模拟递归概念之类的东西。应用是:检查元组的所有元素是否满足某个概念,或检查类型树中所有节点的概念。
【问题讨论】:
-
至少对于带有附加选项
-fconcepts-diagnostics-depth=2的g++,我得到了为什么foo1()无效的信息。 clang 不显示此附加信息。
标签: c++ g++ clang c++20 c++-concepts