[c++] c++17 在编译期判断是否存在某个函数
Posted adream307
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[c++] c++17 在编译期判断是否存在某个函数相关的知识,希望对你有一定的参考价值。
#include <bits/stdc++.h>
namespace detail
template <class Default, class AlwaysVoid, template <class...> class Op,
class... Args>
struct detector
using value_t = std::false_type;
using type = Default;
;
template <class Default, template <class...> class Op, class... Args>
struct detector<Default, std::void_t<Op<Args...>>, Op, Args...>
// Note that std::void_t is a C++17 feature
using value_t = std::true_type;
using type = Op<Args...>;
;
// namespace detail
struct nonesuch
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
;
template <template <class...> class Op, class... Args>
using is_detected =
typename detail::detector<nonesuch, void, Op, Args...>::value_t;
template <template <class...> class Op, class... Args>
using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type;
template <class Default, template <class...> class Op, class... Args>
using detected_or = detail::detector<Default, void, Op, Args...>;
template <template <class...> class Op, class... Args>
constexpr bool is_detected_v = is_detected<Op, Args...>::value;
struct Detectors
template <typename T, typename Arg>
using handle_t = decltype(std::declval<T>().handle(std::declval<Arg>()));
template <typename T, typename Arg>
using op_t = decltype(std::declval<T>()(std::declval<Arg>()));
;
template <typename TDerived>
struct Base : public Detectors
template <typename T>
void entrance(const T& t)
if constexpr (is_detected_v<handle_t, TDerived, T>)
static_cast<TDerived*>(this)->handle(t);
else if constexpr (is_detected_v<op_t, TDerived, T>)
(*static_cast<TDerived*>(this))(t);
else
std::cout << "default handler, type = " << typeid(t).name()
<< std::endl;
;
class D1 : public Base<D1>
public:
void handle(const int& x)
std::cout << "D1, int handle, x = " << x << std::endl;
;
class D2 : public Base<D2>
public:
void operator()(const std::string& str)
std::cout << "D2, string handle, str = " << str << std::endl;
;
struct ValueBase ;
struct IntValue : public ValueBase
int val;
;
struct StrValue : public ValueBase
std::string str;
;
class D3 : public Base<D3>
public:
void handle(const ValueBase& val)
std::cout << "D3, value base handler" << std::endl;
void handle(const StrValue &val)
std::cout << "D3, str value handler, str = " << val.str << std::endl;
;
int main()
D1 d1;
d1.entrance(int(10));
d1.entrance(std::string("123"));
D2 d2;
d2.entrance(int(10));
d2.entrance(std::string("123"));
D3 d3;
IntValue iv;
StrValue sv;
sv.str = "123";
d3.entrance(iv);
d3.entrance(sv);
return 0;
程序输出
D1, int handle, x = 10
default handler, type = Ss
default handler, type = i
D2, string handle, str = 123
D3, value base handler
基类 Base
定义了入口函数 entrance
,如果子类定义了针对特定类型的处理函数 handle
,则调用子类处理函数,否则直接调用基类的 else
分支。
因为 D1
定义类针对 int
的处理函数,所以 d1.entrance(int(10)
最后调用 D1::handle(const int &)
,同样道理应为 D1
未定义针对 std::string
的处理函数,所以 d1.entrance(std::string(10))
最后调用基类的 else
分支代码
参考资料
以上是关于[c++] c++17 在编译期判断是否存在某个函数的主要内容,如果未能解决你的问题,请参考以下文章