C++20 概念使用示例
改编自 ,你可以做一些鸭式打字:
#include <cassert>
#include <concepts>
struct ClassWithMyFunc {
int myFunc() {
return 1;
}
};
struct ClassWithoutMyFunc {};
// Concept HasMyFunc: type 'T' has `.myFunc` and
// its return is convertible to int.
template<typename T>
concept HasMyFunc= requires(T a) {
{ a.myFunc() } -> std::convertible_to<int>;
};
// Constrained function template
template<HasMyFunc T>
int f(T t) {
return t.myFunc() + 1;
}
int main() {
assert(f(ClassWithMyFunc()) == 2);
// assert(f(ClassWithoutMyFunc()) == 2);
}
编译运行:
g++ -ggdb3 -O0 -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
如果我们取消注释 // assert(f(ClassWithoutMyFunc()) == 2); 行,它会按预期失败:
In file included from /usr/include/c++/10/cassert:44,
from main.cpp:1:
main.cpp: In function ‘int main()’:
main.cpp:27:34: error: use of function ‘int f(T) [with T = ClassWithoutMyFunc]’ with unsatisfied constraints
27 | assert(f(ClassWithoutMyFunc()) == 2);
| ^
main.cpp:21:5: note: declared here
21 | int f(T t) {
| ^
main.cpp:21:5: note: constraints not satisfied
main.cpp: In instantiation of ‘int f(T) [with T = ClassWithoutMyFunc]’:
main.cpp:27:5: required from here
main.cpp:15:9: required for the satisfaction of ‘HasMyFunc<T>’ [with T = ClassWithoutMyFunc]
main.cpp:15:20: in requirements with ‘T a’ [with T = ClassWithoutMyFunc]
main.cpp:16:15: note: the required expression ‘a.myFunc()’ is invalid
16 | { a.myFunc() } -> std::convertible_to<int>;
| ~~~~~~~~^~
cc1plus: note: set ‘-fconcepts-diagnostics-depth=’ to at least 2 for more detail
需要多个基类
如果您确实需要某些基类之一:
#include <concepts>
#include <type_traits>
struct Base1 {};
struct Base2 {};
struct Derived1 : public Base1 {};
struct Derived2 : public Base2 {};
struct NotDerived {};
template<typename T>
concept HasBase1Or2= std::is_base_of<Base1, T>::value || std::is_base_of<Base2, T>::value;
template<HasBase1Or2 T>
void f(T) {}
int main() {
f(Derived1());
f(Derived2());
// f(NotDerived());
}
如果我们取消注释 // f(NotDerived()); 行,它会按预期失败:
main.cpp: In function ‘int main()’:
main.cpp:22:19: error: use of function ‘void f(T) [with T = NotDerived]’ with unsatisfied constraints
22 | f(NotDerived());
| ^
main.cpp:17:6: note: declared here
17 | void f(T) {}
| ^
main.cpp:17:6: note: constraints not satisfied
main.cpp: In instantiation of ‘void f(T) [with T = NotDerived]’:
main.cpp:22:19: required from here
main.cpp:13:9: required for the satisfaction of ‘HasBase1Or2<T>’ [with T = NotDerived]
main.cpp:13:55: note: no operand of the disjunction is satisfied
13 | concept HasBase1Or2= std::is_base_of<Base1, T>::value ||
| ~~~~~~^~
14 | std::is_base_of<Base2, T>::value;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: note: set ‘-fconcepts-diagnostics-depth=’ to at least 2 for more detail
在 Ubuntu 21.04 GCC 10.3.0 上测试。
GCC 10 似乎已经实现了它:https://gcc.gnu.org/gcc-10/changes.html,你可以得到它as a PPA on Ubuntu 20.04。 https://godbolt.org/ GCC 10.1 在 Ubuntu 20.04 上无法识别 concept。