70 lines
2.5 KiB
C++
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
|