我想检查struct / class的属性是否符合我的概念要求,但是编译器会抱怨。
示例:
struct N
{
char value;
auto Get() { return value; }
};
struct M
{
int value;
auto Get() { return value; }
};
void func3( auto n )
requires requires
{
//{ n.Get() } -> std::same_as<int>;
{ n.value } -> std::same_as<int>;
}
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void func3( auto n )
requires requires
{
//{ n.Get() } -> std::same_as<char>;
{ n.value } -> std::same_as<char>;
}
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int main()
{
M m;
N n;
func3( n );
func3( m );
}
导致(gcc 10.1.1)的消息多一些
main.cpp: In function 'int main()':
main.cpp:202:18: error: no matching function for call to 'func3(N&)'
202 | func3( n );
| ^
main.cpp:154:10: note: candidate: 'void func3(auto:15) requires requires{{func3::n.value} -> decltype(auto) [requires std::same_as<<placeholder>, int>];} [with auto:15 = N]'
154 | void func3( auto n )
| ^~~~~
main.cpp:154:10: note: constraints not satisfied
main.cpp: In instantiation of 'void func3(auto:15) requires requires{{func3::n.value} -> decltype(auto) [requires std::same_as<<placeholder>, int>];} [with auto:15 = N]':
main.cpp:202:18: required from here
main.cpp:154:10: required by the constraints of 'template<class auto:15> void func3(auto:15) requires requires{{func3::n.value} -> decltype(auto) [requires std::same_as<<placeholder>, int>];}'
main.cpp:155:18: in requirements [with auto:15 = N]
main.cpp:158:13: note: 'n.value' does not satisfy return-type-requirement
158 | { n.value } -> std::same_as<int>;
| ~~^~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
main.cpp:165:10: note: candidate: 'void func3(auto:16) requires requires{{func3::n.value} -> decltype(auto) [requires std::same_as<<placeholder>, char>];} [with auto:16 = N]'
165 | void func3( auto n )
| ^~~~~
main.cpp:165:10: note: constraints not satisfied
main.cpp: In instantiation of 'void func3(auto:16) requires requires{{func3::n.value} -> decltype(auto) [requires std::same_as<<placeholder>, char>];} [with auto:16 = N]':
main.cpp:202:18: required from here
main.cpp:165:10: required by the constraints of 'template<class auto:16> void func3(auto:16) requires requires{{func3::n.value} -> decltype(auto) [requires std::same_as<<placeholder>, char>];}'
main.cpp:166:18: in requirements [with auto:16 = N]
main.cpp:169:13: note: 'n.value' does not satisfy return-type-requirement
169 | { n.value } -> std::same_as<char>;
| ~~^~~~~
main.cpp:203:18: error: no matching function for call to 'func3(M&)'
203 | func3( m );
| ^
main.cpp:154:10: note: candidate: 'void func3(auto:15) requires requires{{func3::n.value} -> decltype(auto) [requires std::same_as<<placeholder>, int>];} [with auto:15 = M]'
154 | void func3( auto n )
| ^~~~~
main.cpp:154:10: note: constraints not satisfied
main.cpp: In instantiation of 'void func3(auto:15) requires requires{{func3::n.value} -> decltype(auto) [requires std::same_as<<placeholder>, int>];} [with auto:15 = M]':
main.cpp:203:18: required from here
检查Get()
函数返回类型的版本可以正常工作。怎么了?
答案 0 :(得分:3)
GCC实际上是正确的(拒绝代码时,不要胡说八道)。引用标准
[expr.prim.req.compound] / 1.3
- 如果存在return-type-requirement,则:
- 执行将模板参数(如果有)替换为return-type-requirement。
- 应满足
decltype((E))
的类型约束的立即声明的约束([temp.param])。
E
是我们的表达,即n.value
。
现在,decltype(n.value)
是char
或int
,这是因为decltype
has a special rule for class member access and id expressions。但是decltype((n.value))
是char&
或int&
。处理通用表达式(例如带括号的类成员访问权限)时,值类别以decltype
的类型编码。
您的示例在修改后可以在GCC中使用
void func3( auto n )
requires requires
{
//{ n.Get() } -> std::same_as<int>;
{ n.value } -> std::same_as<int&>;
}
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void func3( auto n )
requires requires
{
//{ n.Get() } -> std::same_as<char>;
{ n.value } -> std::same_as<char&>;
}
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
答案 1 :(得分:0)
根据[expr.prim.req.compound]/1.3
如果存在返回类型要求,则:
将模板参数(如果有)替换为return-type-requirement。
应满足
decltype((E))
的类型约束的立即声明的约束([temp.param])。 [示例:给定 概念C
和D
,requires { { E1 } -> C; { E2 } -> D<A1, ⋯, An>; };
等同于
requires { E1; requires C<decltype((E1))>; E2; requires D<decltype((E2)), A1, ⋯, An>; };
(包括
n
为零的情况)。 -结束示例 ]
并且从[dcl.type.decltype]/1开始,尤其是[dcl.type.decltype]/1.5
对于表达式
E
,由decltype(E)
表示的类型定义为 如下:
- [...]
- (1.5),否则,如果
E
是左值,decltype(E)
是T&
,其中T
是{{1 }};
因此,由于E
是value
表达式中的lvalue
,因此 return-type-requirement { n.value } -> std::same_as<int>;
的类型约束-> std::same_as<...>;
表达式需要与返回类型{ n.value }
相匹配:
int&