C++ 概念:无论 return 类型是什么,检查 method/operator 是否存在
C++ concept: check if a method/operator exists no matter what return type is
假设我正在编写一个模板函数,它想在其模板参数上调用 operator+=
并且不关心它是否 return 是新值(T
类型), void
或其他任何内容。例如:
template<class T>
void incrementAll(T *array, int size, T value) {
for (int i = 0; i < size; ++i) {
array[i] += value;
}
}
我想对此函数进行约束:使其需要 T
上的 concept
。但是,我找不到对 return 类型没有任何要求的。我能想到的唯一想法是 std::convertible_to<void>
(因为我们可以将任何值转换为 void,对吧?),但它失败了:
#include <concepts>
template<class T>
concept Incrementable = requires(T a, T b) {
{a += b} -> std::convertible_to<void>;
};
template<class T> requires Incrementable<T>
void incrementAll(T *array, int size, T value) {
for (int i = 0; i < size; ++i) {
array[i] += value;
}
}
int main() {
int arr[] = {1};
incrementAll(arr, 1, 1);
}
nikolay@KoLin:~$ g++ another_tmp.cpp -std=c++20 -fconcepts-diagnostics-depth=10
another_tmp.cpp: In function ‘int main()’:
another_tmp.cpp:17:21: error: no matching function for call to ‘incrementAll(int [1], int, int)’
17 | incrementAll(arr, 1, 1);
| ~~~~~~~~~~~~^~~~~~~~~~~
another_tmp.cpp:9:6: note: candidate: ‘template<class T> requires Incrementable<T> void incrementAll(T*, int, T)’
9 | void incrementAll(T *array, int size, T value) {
| ^~~~~~~~~~~~
another_tmp.cpp:9:6: note: template argument deduction/substitution failed:
another_tmp.cpp:9:6: note: constraints not satisfied
another_tmp.cpp: In substitution of ‘template<class T> requires Incrementable<T> void incrementAll(T*, int, T) [with T = int]’:
another_tmp.cpp:17:14: required from here
another_tmp.cpp:4:9: required for the satisfaction of ‘Incrementable<T>’ [with T = int]
another_tmp.cpp:4:25: in requirements with ‘T a’, ‘T b’ [with T = int]
another_tmp.cpp:5:12: note: ‘a += b’ does not satisfy return-type-requirement, because
5 | {a += b} -> std::convertible_to<void>;
| ~~^~~~
another_tmp.cpp:5:10: error: deduced expression type does not satisfy placeholder constraints
5 | {a += b} -> std::convertible_to<void>;
| ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
another_tmp.cpp:5:10: note: constraints not satisfied
In file included from another_tmp.cpp:1:
/usr/include/c++/11.2.0/concepts:72:13: required for the satisfaction of ‘convertible_to<decltype(auto) [requires std::convertible_to<<placeholder>, void>], void>’ [with decltype(auto) [requires std::convertible_to<<placeholder>, void>] = int&]
/usr/include/c++/11.2.0/concepts:72:30: note: the expression ‘is_convertible_v<_From, _To> [with _From = int&; _To = void]’ evaluated to ‘false’
72 | concept convertible_to = is_convertible_v<_From, _To>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
那么,这里定义的正确概念是什么?
如果您不关心它的 return 类型是什么,那么您可以简单地使用 requires
子句来要求表达式 a += b
为 well-formed :
template<class T>
concept Incrementable = requires(T a, T b) {
a += b;
};
不过,这样的概念对于可增量类型来说似乎过于宽松,要求return类型像{a += b} -> same_as<T&>
一样T&
并命名为[=似乎更合适15=] 什么的。
假设我正在编写一个模板函数,它想在其模板参数上调用 operator+=
并且不关心它是否 return 是新值(T
类型), void
或其他任何内容。例如:
template<class T>
void incrementAll(T *array, int size, T value) {
for (int i = 0; i < size; ++i) {
array[i] += value;
}
}
我想对此函数进行约束:使其需要 T
上的 concept
。但是,我找不到对 return 类型没有任何要求的。我能想到的唯一想法是 std::convertible_to<void>
(因为我们可以将任何值转换为 void,对吧?),但它失败了:
#include <concepts>
template<class T>
concept Incrementable = requires(T a, T b) {
{a += b} -> std::convertible_to<void>;
};
template<class T> requires Incrementable<T>
void incrementAll(T *array, int size, T value) {
for (int i = 0; i < size; ++i) {
array[i] += value;
}
}
int main() {
int arr[] = {1};
incrementAll(arr, 1, 1);
}
nikolay@KoLin:~$ g++ another_tmp.cpp -std=c++20 -fconcepts-diagnostics-depth=10
another_tmp.cpp: In function ‘int main()’:
another_tmp.cpp:17:21: error: no matching function for call to ‘incrementAll(int [1], int, int)’
17 | incrementAll(arr, 1, 1);
| ~~~~~~~~~~~~^~~~~~~~~~~
another_tmp.cpp:9:6: note: candidate: ‘template<class T> requires Incrementable<T> void incrementAll(T*, int, T)’
9 | void incrementAll(T *array, int size, T value) {
| ^~~~~~~~~~~~
another_tmp.cpp:9:6: note: template argument deduction/substitution failed:
another_tmp.cpp:9:6: note: constraints not satisfied
another_tmp.cpp: In substitution of ‘template<class T> requires Incrementable<T> void incrementAll(T*, int, T) [with T = int]’:
another_tmp.cpp:17:14: required from here
another_tmp.cpp:4:9: required for the satisfaction of ‘Incrementable<T>’ [with T = int]
another_tmp.cpp:4:25: in requirements with ‘T a’, ‘T b’ [with T = int]
another_tmp.cpp:5:12: note: ‘a += b’ does not satisfy return-type-requirement, because
5 | {a += b} -> std::convertible_to<void>;
| ~~^~~~
another_tmp.cpp:5:10: error: deduced expression type does not satisfy placeholder constraints
5 | {a += b} -> std::convertible_to<void>;
| ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
another_tmp.cpp:5:10: note: constraints not satisfied
In file included from another_tmp.cpp:1:
/usr/include/c++/11.2.0/concepts:72:13: required for the satisfaction of ‘convertible_to<decltype(auto) [requires std::convertible_to<<placeholder>, void>], void>’ [with decltype(auto) [requires std::convertible_to<<placeholder>, void>] = int&]
/usr/include/c++/11.2.0/concepts:72:30: note: the expression ‘is_convertible_v<_From, _To> [with _From = int&; _To = void]’ evaluated to ‘false’
72 | concept convertible_to = is_convertible_v<_From, _To>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
那么,这里定义的正确概念是什么?
如果您不关心它的 return 类型是什么,那么您可以简单地使用 requires
子句来要求表达式 a += b
为 well-formed :
template<class T>
concept Incrementable = requires(T a, T b) {
a += b;
};
不过,这样的概念对于可增量类型来说似乎过于宽松,要求return类型像{a += b} -> same_as<T&>
一样T&
并命名为[=似乎更合适15=] 什么的。