#include <iostream> #include <string> // Uncomment this declaration to change behavIoUr //void draw(const std::string&); template <typename T> concept bool Drawable() { return requires (const T& t) { { draw(t) } }; } void draw(const std::string& s) { std::cout << s << "\n"; } int main() { static_assert(Drawable<std::string>()); // Fails }
在这里我定义一个简单的概念,Drawable,它的目的是要求给定一个类型为const T&,draw(t)的编译参数.
然后我定义一个函数draw(const std :: string&),它将字符串“绘制”为cout.最后,我检查std :: string是否匹配Drawable概念 – 我本来会期望它,因为在调用static_assert时,适当的draw()函数在范围内.
但是,静态断言失败,除非我在概念定义之前包含一个draw(const std :: string&)声明,而且我不知道为什么.
这是预期的行为与概念,还是我做错了?
解决方法
template<typename T> concept bool C = requires (T a,T b) { a + b; };
这是一个简单的要求,[expr.prim.req.simple],它检查表达式的有效性.重写我们的示例以匹配表单:
template<typename T> concept bool Drawable = requires (const T& x) { draw(x); };
我们可以看到我们的语法很好.好的,n4377怎么说?
[expr.prim.req]/1 A requires-expression provides a concise way to
express requirements on template arguments. A requirement is one that
can be checked by name lookup (3.4) or by checking properties of types
and expressions.[expr.prim.req]/6 The requirement-body is comprised of a sequence of
requirements. These requirements may refer to local parameters,
template parameters,and any other declarations visible from the
enclosing context. …
说得通.我们知道包围的上下文是全局命名空间,所以n4140说什么?
[basic.lookup.unqual]/1 In all the cases listed in 3.4.1,the scopes
are searched for a declaration in the order listed in each of the
respective categories; name lookup ends as soon as a declaration is
found for the name. If no declaration is found,the program is
ill-formed.A name used in the definition of a function following the function’s
declarator-id that is a member of namespaceN
(where,only for the purpose of exposition,N
could represent the global scope) shall be
declared before its use in the block in which it is used or in one of
its enclosing blocks (6.3) or,shall be declared before its use in
namespaceN
…
由于这个概念适用于该功能,所以上面的段落适用.