wrenpp/include/wrenpp/has_method.hpp
2020-04-30 23:33:54 +02:00

70 lines
2.5 KiB
C++

/* Copyright 2020, Michele Santullo
* This file is part of wrenpp.
*
* Wrenpp is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Wrenpp is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <type_traits>
//see https://stackoverflow.com/a/10707822
#define define_method_info(method_name, pretty_name, ret_type, ...) \
class method_ ## pretty_name { \
typedef std::integral_constant<int, 0> no_method_t; \
typedef std::integral_constant<int, 1> has_method_t; \
typedef std::integral_constant<int, 2> has_static_method_t; \
template<typename A, typename... Args> \
static has_method_t test(ret_type (A::*)(Args...)) { \
return {}; \
} \
template <typename A, typename... Args> \
static has_static_method_t test(ret_type (*)(Args...)) { \
return {}; \
} \
template <typename A, typename... Args> \
static auto test(decltype(std::declval<A>().method_name(std::declval<Args>()...))*,void *) { \
typedef decltype(test<A, Args...>(&A::method_name)) return_type; \
return return_type{}; \
} \
template<typename A, typename... Args> \
static no_method_t test(...) { \
return {}; \
} \
public: \
template< typename T> \
class exists { \
typedef decltype(test<T, __VA_ARGS__>(0,0)) found_t; \
public: \
static const constexpr bool value = (found_t::value != no_method_t::value); \
}; \
template <typename T> \
class is_static { \
typedef decltype(test<T, __VA_ARGS__>(0,0)) found_t; \
public: \
static const constexpr bool value = (found_t::value == has_static_method_t::value); \
}; \
template <typename T> struct static_ptr { \
typedef ret_type (*type)(__VA_ARGS__); \
}; \
template <typename T> struct nonstatic_ptr { \
typedef ret_type (T::*type)(__VA_ARGS__); \
}; \
template <typename T> struct ptr { \
typedef typename std::conditional<is_static<T>::value, typename static_ptr<T>::type, typename std::conditional<exists<T>::value, typename nonstatic_ptr<T>::type, void>::type>::type type; \
}; \
}
namespace wren {
} //namespace wren