C++ named requirements: Callable
一个 Callable 类型是适用于 INVOKE (用于,e.g.,srtd::function, std::bind,和 std::thread::thread) 操作的类型。操作可能被显式的使用库函数std::invoke
执行。
Requirements:
类型T满足Callable
,如果有:
- f, 一个类型为T的对象
- ArgTypes,合适的参数类型列表
- R,合适的返回值
下列表达式必须合法:
INVOKE<R>(f, std::declval<ArgTypes>()...)
该表达式在未计算的上下文中,表达式良构。
如果 R 是 cv-qualified 的 void
,INVOKE<R>(f, t1, t2,…,tN) 被定义为 static_cast<void>(INVOKE(f, t1, t2,..., tN))
,否则,INVOKE<R>(f, t1, t2, … , tN) 将隐式转换为R。
INVOKE(f, t1, t2, …, tN) 的定义如下:
- 如果 f 是类 T 的成员函数指针:
- 如果
std::is_base_of<T, std::remove_reference_t<decltype(t1)>>::value
为true
,那么INVOKE(f, t1, t2, ..., tN)
等价于(t1.*f(t2, ..., tN))
- 否则,如果
std::remove_cvref_t<decltype(t1)>
是std::reference_wrapper
的特化,那么INVOKE(f, t1, t2, ..., tN)
等价于(t1.get().*f)(t2, ..., tN)
(since C++17) - 否则,如果t1不满足前述的条件,那么
INVOKE(f, t1, t2, ..., tN)
等价于((*t1).*f)(t2, ..., tN)
.
- 如果
- 否则,如果 N == 1 且 f 类 T 的数据成员指针:
- 如果
std::if_base_of<T, std::remove_reference_t<decltype(t1)>>::value
为true
,那么INVOKE(f, t1)
等价于t1.*f
- 否则,如果
std::remove_cvref_t<decltype(t1)>
是std::reference_wrapper
的特化,那么INVOKE(f, t1)
等价于t1.get().*f
(since C++17) - 否则,如果 t1 不满足前述的条件,那么
INVOKE(f, t1)
等价于(*t1).*f
- 如果
- 否则,
INVOKE(f, t1, t2, ..., tN)
等价于f(t1, t2, ..., tN)
(f 是一个FunctionObject
)
Notes
对于成员函数指针和数据成员指针,t1 可能是一个常规的指针或是重载了 operator*
的类类型的对象,例如 std::unique_ptr 或 std::shared_ptr (等价于(*t1).*f(t2, ..., tN)
)。
数据成员的指针式 Callable
的,即使没有函数调用的发生。
Standary library
另外,下列标准库工具接受任何Callable
类型(不仅仅式FunctionObject
)
- function(C++11): 用指定的函数抵用签名封装任何类型的 callable 对象 (class template)
- bind(C++11): 绑定一个或多个参数到函数对象 (function template)
- reference_wrapper(C++11):
CopyConstructible
和CopyAssignable
引用封装器 - thread(C++11): 管理一个分离的线程 (class)
- jthread(C++20): 支持 auto-joining 和 cancellation 的 std::thread (class)
- call_once(C++11): 即使在多个线程中被调用,函数也只被调用一次 (function template)
- async(C++11): 异步的执行函数(潜在的在一个新线程中)并返回一个
std::future
来保存结果 (function template) - packaged_task(C++11): 封装一个函数以存储他的异步取回的返回值 (class template)