Concepts: method signature verification with arguments

I play with concepts. Here is a minimal example when I try to create a concept based on method signatures:

template<typename T> concept bool myConcept() { return requires(T a, int i) { { a.foo() } -> int; { a.bar(i) } -> int; }; } struct Object { int foo() {return 0;} int bar(int) {return 0;} }; static_assert(myConcept<Object>(), "Object does not adhere to myConcept"); 

To my surprise, the entry { a.bar(int) } -> int did not work, so I resorted to adding an additional argument to the requires expression. This seems a little strange, and I was wondering if there is a way to do the same. Another thing that worked was to use something like { a.bar((int)0) } -> int , but I find it worse.

+5
source share
2 answers

Expression validation values, and a.bar(int) is not one. We write

 { a.foo(int) } -> int 

ask the compiler to verify that the specified expression is of type int . It does not make sense.

You have found a valid alternative; the other may be because the type a.bar(x) is independent of the value of x :

 template<typename T> concept bool myConcept() { return requires(T a) { { a.foo() } -> int; { a.bar(0) } -> int; }; } struct Object { int foo() {return 0;} int bar(int) {return 0;} }; static_assert(myConcept<Object>(), "Object does not adhere to myConcept"); 
+6
source

Since the actual type value does not matter, I would suggest using int{} as an argument. In this document, the purpose of the argument is somewhat better, IMO:

 { a.bar(int{}) } -> int; 

Obviously, this will not work with types for which there is no default constructor. In templates, you can use std::declval to work on a similar problem, but here are the GCC errors:

 error: static assertion failed: declval() must not be used! 

But there is nothing that would prevent us from writing an equivalent (but not implemented) function that will be used with concepts, for example:

 #include <type_traits> template <class T> typename std::add_rvalue_reference<T>::type makeval(); template<typename T> concept bool myConcept() { return requires(T a, int i) { { a.foo() } -> int; { a.bar(makeval<int>()) } -> int; }; } struct Object { int foo() {return 0;} int bar(int) {return 0;} }; static_assert(myConcept<Object>(), "Object does not adhere to myConcept"); 
+3
source

Source: https://habr.com/ru/post/1261655/


All Articles