检查类是否有可能重载的函数调用运算符 [英] Check if a class has a possibly-overloaded function call operator
问题描述
我想知道是否有可能在 C ++ 20
中实现特征以检查类型 T
这样,它就有一个可能重载/可能是模板化的函数调用运算符: operator()
。
I am wondering whether it would be possible to implement a trait in C++20
to check if a type T
is such that it has a possibly overloaded/possibly templated function call operator: operator()
.
// Declaration
template <class T>
struct has_function_call_operator;
// Definition
???
// Variable template
template <class T>
inline constexpr bool has_function_call_operator_v
= has_function_call_operator<T>::value;
这样的代码将导致正确的结果:
so that a code such as the following would lead to the correct result:
#include <iostream>
#include <type_traits>
struct no_function_call_operator {
};
struct one_function_call_operator {
constexpr void operator()(int) noexcept;
};
struct overloaded_function_call_operator {
constexpr void operator()(int) noexcept;
constexpr void operator()(double) noexcept;
constexpr void operator()(int, double) noexcept;
};
struct templated_function_call_operator {
template <class... Args>
constexpr void operator()(Args&&...) noexcept;
};
struct mixed_function_call_operator
: overloaded_function_call_operator
, templated_function_call_operator {
};
template <class T>
struct has_function_call_operator: std::false_type {};
template <class T>
requires std::is_member_function_pointer_v<decltype(&T::operator())>
struct has_function_call_operator<T>: std::true_type {};
template <class T>
inline constexpr bool has_function_call_operator_v
= has_function_call_operator<T>::value;
int main(int argc, char* argv[]) {
std::cout << has_function_call_operator_v<no_function_call_operator>;
std::cout << has_function_call_operator_v<one_function_call_operator>;
std::cout << has_function_call_operator_v<overloaded_function_call_operator>;
std::cout << has_function_call_operator_v<templated_function_call_operator>;
std::cout << has_function_call_operator_v<mixed_function_call_operator>;
std::cout << std::endl;
}
当前它打印 01000
,而不是 01111
。如果从最广泛的意义上说它不可行,则可以认为 T
是可继承的(如果有帮助的话)。只要它们完全符合 C ++ 20
标准,就欢迎使用最奇怪的模板元编程技巧。
Currently it prints 01000
instead of 01111
. If it is not doable in the broadest possible sense, it can be assumed that T
is inheritable if that helps. The weirdest possible template metaprogramming tricks are welcome as long as they are fully compliant with the C++20
standard.
推荐答案
& T :: operator()
对于这3个失败的案例都是模棱两可的。
&T::operator()
is ambiguous for the 3 failing cases.
所以你发现的特征是有一个明确的 operator()
So your traits found is there is an unambiguous operator()
不是 final
,我们可能会将您的特征应用于具有现有继承的 operator()
的(假)类和要测试的类:
As you allow T to be not final
, we might apply your traits to (fake) class with existing inherited operator()
and class to test:
template <class T>
struct has_one_function_call_operator: std::false_type {};
template <class T>
requires std::is_member_function_pointer_v<decltype(&T::operator())>
struct has_one_function_call_operator<T>: std::true_type {};
struct WithOp
{
void operator()() const;
};
template <typename T>
struct Mixin : T, WithOp {};
// if T has no `operator()`, Mixin<T> has unambiguous `operator()` coming from `WithOp`
// else Mixin<T> has ambiguous `operator()`
template <class T>
using has_function_call_operator =
std::bool_constant<!has_one_function_call_operator<Mixin<T>>::value>;
template <class T>
inline constexpr bool has_function_call_operator_v
= has_function_call_operator<T>::value;
这篇关于检查类是否有可能重载的函数调用运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!