Permalink
Fetching contributors…
Cannot retrieve contributors at this time
99 lines (83 sloc) 1.83 KB
#include <type_traits>
#include <vrm/pp.hpp>
#include <iostream>
#include <tuple>
#include <utility>
#include <experimental/tuple>
template <typename T>
struct type_w
{
using type = T;
};
template <typename T>
constexpr type_w<T> type_c{};
template <typename TF>
struct validity_checker
{
template <typename... Ts>
constexpr auto operator()(Ts... ts)
{
return std::is_callable<std::decay_t<TF>(
typename decltype(ts)::type...)>{};
}
};
template <typename T, typename TF>
constexpr auto operator|(T x, validity_checker<TF> vc)
{
return std::apply(vc, x);
}
template <typename TF>
constexpr auto is_valid(TF)
{
return validity_checker<TF>{};
}
// The other `IS_VALID_...` should be generated by a script (or by an higher
// order preprocessor macro).
#define IS_VALID_2_EXPANDER(...) \
is_valid([](auto _0, auto _1) constexpr->decltype(__VA_ARGS__){})
#define IS_VALID_2(type0, type1) \
::std::make_tuple(type_c<type0>, type_c<type1>) | IS_VALID_2_EXPANDER
#define IS_VALID_1_EXPANDER(...) \
is_valid([](auto _0) constexpr->decltype(__VA_ARGS__){})
#define IS_VALID_1(type0) ::std::make_tuple(type_c<type0>) | IS_VALID_1_EXPANDER
#define IS_VALID(...) \
VRM_PP_CAT(IS_VALID_, VRM_PP_ARGCOUNT(__VA_ARGS__))(__VA_ARGS__)
struct Cat
{
Cat() = delete;
void meow() const
{
std::cout << "meow\n";
}
};
struct Dog
{
Dog() = delete;
void bark() const
{
std::cout << "bark\n";
}
};
template <typename T>
auto make_noise(const T& x)
{
if constexpr(IS_VALID(T)(_0.meow()))
{
x.meow();
}
else if constexpr(IS_VALID(T)(_0.bark()))
{
x.bark();
}
else
{
struct cannot_meow_or_bark;
cannot_meow_or_bark{};
}
}
int main()
{
make_noise(Cat{});
make_noise(Dog{});
// make_noise(int{});
}