[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 在编译期判断是否存在某个函数的主要内容,如果未能解决你的问题,请参考以下文章