Skip to content

Instantly share code, notes, and snippets.

@klemens-morgenstern
Created August 7, 2022 11:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save klemens-morgenstern/12d05dc62c17c969ca9015a7ebee6085 to your computer and use it in GitHub Desktop.
Save klemens-morgenstern/12d05dc62c17c969ca9015a7ebee6085 to your computer and use it in GitHub Desktop.
function-describe attempt
#include <boost/describe.hpp>
#include <boost/preprocessor.hpp>
#include <utility>
#include <boost/mp11.hpp>
namespace boost::describe
{
namespace detail {
template<typename Ptr, Ptr Func>
struct describe_function_tag {};
template<typename ... Args, typename Return>
constexpr auto cast_helper(Return (*p)(Args...)) -> Return (*)(Args...)
{
return p;
}
template<typename T>
struct interpret_helper
{
using type = T;
template<typename U>
constexpr interpret_helper<T> operator=(U &&) const;
};
}
template<typename T, T (*Ptr)()>
auto tag_invoke(detail::describe_function_tag<T(*)(), Ptr>, T (*)())
{
return boost::mp11::mp_list<>{};
}
template<typename Ptr, Ptr Func>
auto describe_function()
{
return tag_invoke(detail::describe_function_tag<Ptr, Func>{}, static_cast<Ptr>(Func));
}
}
#define BOOST_DESCRIBE_FUNCTION_TAG_IMPL(Type, ...) ::boost::describe::detail::interpret_helper<Type>{}
#define BOOST_DESCRIBE_FUNCTION_TAG_STEP(i, _ , Value) \
BOOST_PP_COMMA_IF(BOOST_PP_SUB(i, 1)) decltype( BOOST_DESCRIBE_FUNCTION_TAG_IMPL Value)::type
#define BOOST_DESCRIBE_FUNCTION_STEP_DESCRIPTOR_IMPL_2(Type, Name) \
struct Name ## _t \
{ \
using type = Type; \
constexpr static auto name() -> const char (&)[sizeof(#Name)] { return #Name; } \
constexpr static bool has_default() { return false; }\
} Name;
#define BOOST_DESCRIBE_FUNCTION_STEP_DESCRIPTOR_IMPL_3(Type, Name, Default) \
struct Name ## _t \
{ \
using type = Type; \
constexpr static auto name() -> const char (&)[sizeof(#Name)] { return #Name; }\
static decltype(Default) default_value() {return Default; } \
constexpr static bool has_default() { return true; }\
};;
#define BOOST_DESCRIBE_FUNCTION_STEP_DESCRIPTOR_IMPL(...) \
BOOST_PP_OVERLOAD(BOOST_DESCRIBE_FUNCTION_STEP_DESCRIPTOR_IMPL_, __VA_ARGS__)(__VA_ARGS__)
#define BOOST_DESCRIBE_FUNCTION_STEP_DESCRIPTOR_STEP(i, _ , Value) \
BOOST_DESCRIBE_FUNCTION_STEP_DESCRIPTOR_IMPL Value ;
#define BOOST_DESCRIBE_FUNCTION_DEDUCE_TAG_DECL(Invoked...) \
::boost::describe::detail::describe_function_tag<decltype(Invoked), Invoked>, decltype(Invoked)
#define BOOST_DESCRIBE_FUNCTION_STEP_LIST_IMPL(...) BOOST_PP_CAT(BOOST_PP_VARIADIC_ELEM(1, __VA_ARGS__), _t)
#define BOOST_DESCRIBE_FUNCTION_STEP_LIST_STEP(i, _, Value) \
BOOST_PP_COMMA_IF(BOOST_PP_SUB(i, 1)) BOOST_DESCRIBE_FUNCTION_STEP_LIST_IMPL Value
#define BOOST_DESCRIBE_FUNCTION_IMPL(Name, Signature) \
auto tag_invoke(BOOST_DESCRIBE_FUNCTION_DEDUCE_TAG_DECL( \
::boost::describe::detail::cast_helper< BOOST_PP_LIST_FOR_EACH(BOOST_DESCRIBE_FUNCTION_TAG_STEP, _, Signature) >(&Name) )) \
{ \
BOOST_PP_LIST_FOR_EACH(BOOST_DESCRIBE_FUNCTION_STEP_DESCRIPTOR_STEP, _, Signature) \
return ::boost::mp11::mp_list< BOOST_PP_LIST_FOR_EACH(BOOST_DESCRIBE_FUNCTION_STEP_LIST_STEP, _, Signature) >{}; \
} \
#define BOOST_DESCRIBE_FUNCTION(Name, Signature...) BOOST_DESCRIBE_FUNCTION_IMPL(Name, BOOST_PP_VARIADIC_TO_LIST(Signature))
#define BOOST_DESCRIBE_FUNCTION_DEFINE_3(Type, Name, _) Type Name
#define BOOST_DESCRIBE_FUNCTION_DEFINE_2(Type, Name) Type Name
#define BOOST_DESCRIBE_FUNCTION_DEFINE(...) \
BOOST_PP_OVERLOAD(BOOST_DESCRIBE_FUNCTION_DEFINE_, __VA_ARGS__)(__VA_ARGS__)
#define BOOST_DESCRIBE_FUNCTION_DEFINE_STEP(i, _ , Value) \
BOOST_PP_COMMA_IF(BOOST_PP_SUB(i, 1)) BOOST_DESCRIBE_FUNCTION_DEFINE Value
#define BOOST_DECLARE_FUNCTION_IMPL(Name, Signature) \
Name ( BOOST_PP_LIST_FOR_EACH(BOOST_DESCRIBE_FUNCTION_DEFINE_STEP, _, Signature) ); \
BOOST_DESCRIBE_FUNCTION_IMPL(Name, Signature);
#define BOOST_DECLARE_FUNCTION(Name, Signature...) \
BOOST_DECLARE_FUNCTION_IMPL(Name, BOOST_PP_VARIADIC_TO_LIST(Signature))
int test_func(double value, const char * description = "default");
BOOST_DESCRIBE_FUNCTION(test_func, (double, value), (const char *, description, "default"));
int BOOST_DECLARE_FUNCTION(test_func2, (double, value), (const char *, description, "default"));
void foobar()
{
boost::describe::describe_function<decltype(&test_func), &test_func>();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment