std::invocable
有什么区别和 std::regular_invocable
?根据来自的描述
https://en.cppreference.com/w/cpp/concepts/invocable我希望 std::regular_invocable
概念不允许在调用时更改函数对象的状态(或至少调用的结果应始终返回相同的结果)。
为什么下面的代码会编译?
用命令编译:g++-10 -std=c++2a ./main.cc
.
#include <iostream>
#include <concepts>
using namespace std;
template<std::regular_invocable F>
auto call_with_regular_invocable_constraint(F& f){
return f();
}
template<std::invocable F>
auto call_with_invocable_constraint(F& f){
return f();
}
class adds_one {
int state{0};
public:
int operator()() {
state++;
return state;
}
};
int main()
{
auto immutable_function_object([]() { return 1; });
adds_one mutable_function_object;
// I would expect only first three will be compiled and the last one will fail to compile because the procedure is
// not regular (that is does not result in equal outputs given equal inputs).
cout << call_with_invocable_constraint(immutable_function_object) << endl;
cout << call_with_invocable_constraint(mutable_function_object) << endl;
cout << call_with_regular_invocable_constraint(immutable_function_object) << endl;
cout << call_with_regular_invocable_constraint(mutable_function_object) << endl; // Compiles!
}
程序的输出:1
1
1
2
最佳答案
来自 the reference :
Notes
The distinction between invocable and regular_invocable is purely semantic.
这意味着编译器无法通过概念系统强制区分,因为它只能检查句法属性。
从介绍到concepts library :
In general, only the syntactic requirements can be checked by the compiler. If the validity or meaning of a program depends whether a sequenced of template arguments models a concept, and the concept is satisfied but not modeled, or if a semantic requirement is not met at the point of use, the program is ill-formed, no diagnostic required.
假设,我们可以这样写:
template< class F, class... Args >
concept regular_invocable = invocable<F, Args...> &&
requires(F&& f, Args&&... args) {
auto prev = f;
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
assert(f == prev);
// TODO assert that `args` are unchanged
// TODO assert that invoking `f` a second time gives the same result
};
然而,这实际上不会测试断言是否成立,因为 requires
子句不在运行时调用,而只在编译时检查。
关于c++ - std::invocable 和 std::regular_invocable 概念之间有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64739274/