std::is_invocable 用于测试任意方法是否存在的语法(不仅是运算符())
std::is_invocable syntax for testing existence of an arbitrary method (not only operator())
在C++17中,我知道我可以写:
#include <type_traits>
struct A
{
size_t operator()(double x) const { return 1; };
};
int main()
{
static_assert(std::is_invocable_r_v<size_t, A, double>);
}
但是现在我想使用 std::is_invocable 来测试任意方法的存在(这里是size(double)
方法(:
#include <type_traits>
struct A
{
size_t size(double x) const { return 1; };
};
int main()
{
static_assert(std::is_invocable_r_v<size_t, ???, double>);
}
问题是必须如何填充"???"才能使其工作?
使用检测习惯用语:
template <typename T, typename... Args>
using call_size_t = decltype(std::declval<T>().size(std::declval<Args>()...);
template <typename R, typename T, typename... Args>
using is_size_callable = is_detected_convertible<R, call_size_t, T, Args...>;
static_assert(is_size_callable<size_t, A, double>::value);
这样做的好处是可以使用重载的成员函数size
、模板或默认参数。
在 C++20 中,概念:
template <typename T, typename R, typename... Args>
concept is_size_callable = requires (T t, Args... args) {
{ t.size(std::forward<Args>(args)...) } -> std::convertible_to<R>;
};
static_assert(is_size_callable<A, size_t, double>);
我翻转了参数以将T
放在第一位,因为这将允许类型约束语法:
template <is_size_callable<size_t, double> T>
void foo(T );
foo(A{});
c++20:
#define RETURNS( ... )
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }
#define METHOD( ... )
[]( auto&& self, auto&&...args )
RETURNS( decltype(self)(self).__VA_ARGS__( decltype(args)(args)... ) )
struct A
{
std::size_t size(double x) const { return 1; };
};
int main()
{
static_assert(std::is_invocable_r<std::size_t, decltype(METHOD(size)), A&, double>{});
}
和 C++17:
#define RETURNS( ... )
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }
#define METHOD( ... )
[]( auto&& self, auto&&...args )
RETURNS( decltype(self)(self).__VA_ARGS__( decltype(args)(args)... ) )
auto call_size = METHOD(size);
struct A
{
std::size_t size(double x) const { return 1; };
};
int main()
{
static_assert(std::is_invocable_r<std::size_t, decltype(call_size), A&, double>{});
}
(注意:我使用...
因为宏不知道<,>
样式括号和逗号(
我刚刚意识到正确的语法是:
static_assert(std::is_invocable_r_v<size_t, decltype(&A::size), A, double>);
这是一个工作示例
// -*- compile-command: "g++ -std=c++17 demo.cpp -o demo"; -*-
#include <type_traits>
struct A
{
size_t operator()(double x) const { return 1; };
size_t size(double x) const { return 1; };
};
int main()
{
static_assert(std::is_invocable_r_v<size_t, A, double>);
static_assert(std::is_invocable_r_v<size_t, decltype(&A::size), A, double>);
return EXIT_SUCCESS;
}
相关文章:
- C++语法运算符功能?
- C++ 运算符修改/元编程策略,用于不那么冗长的语法
- 无效删除运算符语法
- std::is_invocable 用于测试任意方法是否存在的语法(不仅是运算符())
- 这个typedef和转换运算符语法是什么意思
- C++ lambda 和运算符语法
- 如何使用 Boost Spirit x3 编写具有两个后操作数语法的二进制运算符?
- 将强制转换运算符重载到 std::map 的正确语法是什么
- 奇怪的语法构造 - 应用于 typedef 的运算符 () 使用 VS2015 成功编译
- 如何使用删除 [] 运算符清除动态分配的内存?(无法使用常规删除语法清除)
- 适用于全局模板运算符指定模板参数的适当语法
- C 中的controad()括号的语法运算符
- 全局新运算符调用语法
- 模板的赋值运算符(成员函数)实现的正确语法
- 这个奇怪的条件运算符语法是什么
- 为什么在使用初始化语法时不调用转换运算符,为什么 clang 错误消息看起来是错误的
- 运算符重载中的C++语法不明确
- 使用范围解析运算符时的语法错误
- 正在调用运算符()语法
- 条件运算符语法