Created
August 24, 2022 14:39
-
-
Save Sunday111/e6b52180ba6aab726739c7728a603aba to your computer and use it in GitHub Desktop.
Get function or method information by type
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <type_traits> | |
#include <tuple> | |
template<typename T> | |
struct Signature; | |
// function | |
template<typename Ret_, typename... Args_> | |
struct Signature<Ret_(*)(Args_...)> { | |
using Ret = Ret_; | |
using Class = void; | |
using Args = std::tuple<Args_...>; | |
static constexpr bool Const = false; | |
static constexpr bool Noexcept = false; | |
static constexpr bool Volatile = false; | |
static constexpr bool Pure = true; | |
static constexpr bool LRef = false; | |
static constexpr bool RRef = false; | |
}; | |
// noexcept function | |
template<typename Ret_, typename... Args_> | |
struct Signature<Ret_(*)(Args_...) noexcept> : Signature<Ret_(*)(Args_...)> { | |
static constexpr bool Noexcept = true; | |
}; | |
// method | |
template<typename Ret_, typename Class_, typename... Args_> | |
struct Signature<Ret_(Class_::*)(Args_...)> : Signature<Ret_(*)(Args_...)> { | |
using Class = Class_; | |
static constexpr bool Pure = false; | |
}; | |
#ifndef SIGNATURE_METHOD_SPECIALIZATION | |
#define SIGNATURE_METHOD_SPECIALIZATION(qualifiers)\ | |
template<typename Ret_, typename Class_, typename... Args_>\ | |
struct Signature<Ret_(Class_::*)(Args_...) qualifiers> : Signature<Ret_(Class_::*)(Args_...)> | |
#else | |
static_assert(false, "Name collision with test macro"); | |
#endif | |
SIGNATURE_METHOD_SPECIALIZATION(&) { | |
static constexpr bool LRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(&&) { | |
static constexpr bool RRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const) { | |
static constexpr bool Const = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const &) { | |
static constexpr bool Const = true; | |
static constexpr bool LRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const &&) { | |
static constexpr bool Const = true; | |
static constexpr bool RRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(noexcept) { | |
static constexpr bool Noexcept = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(& noexcept) { | |
static constexpr bool Noexcept = true; | |
static constexpr bool LRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(&& noexcept) { | |
static constexpr bool Noexcept = true; | |
static constexpr bool RRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(volatile) { | |
static constexpr bool Volatile = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(volatile &) { | |
static constexpr bool Volatile = true; | |
static constexpr bool LRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(volatile &&) { | |
static constexpr bool Volatile = true; | |
static constexpr bool RRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const noexcept) { | |
static constexpr bool Const = true; | |
static constexpr bool Noexcept = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const & noexcept) { | |
static constexpr bool Const = true; | |
static constexpr bool Noexcept = true; | |
static constexpr bool LRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const && noexcept) { | |
static constexpr bool Const = true; | |
static constexpr bool Noexcept = true; | |
static constexpr bool RRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const volatile) { | |
static constexpr bool Const = true; | |
static constexpr bool Volatile = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const volatile &) { | |
static constexpr bool Const = true; | |
static constexpr bool Volatile = true; | |
static constexpr bool LRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const volatile &&) { | |
static constexpr bool Const = true; | |
static constexpr bool Volatile = true; | |
static constexpr bool RRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(volatile noexcept) { | |
static constexpr bool Volatile = true; | |
static constexpr bool Noexcept = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(volatile & noexcept) { | |
static constexpr bool Volatile = true; | |
static constexpr bool Noexcept = true; | |
static constexpr bool LRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(volatile && noexcept) { | |
static constexpr bool Volatile = true; | |
static constexpr bool Noexcept = true; | |
static constexpr bool RRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const volatile noexcept) { | |
static constexpr bool Const = true; | |
static constexpr bool Volatile = true; | |
static constexpr bool Noexcept = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const volatile & noexcept) { | |
static constexpr bool Const = true; | |
static constexpr bool Volatile = true; | |
static constexpr bool Noexcept = true; | |
static constexpr bool LRef = true; | |
}; | |
SIGNATURE_METHOD_SPECIALIZATION(const volatile && noexcept) { | |
static constexpr bool Const = true; | |
static constexpr bool Volatile = true; | |
static constexpr bool Noexcept = true; | |
static constexpr bool RRef = true; | |
}; | |
#undef SIGNATURE_METHOD_SPECIALIZATION | |
#ifndef SIGNATURE_TEST_METHOD | |
#define SIGNATURE_TEST_METHOD(pre_qualifiers, name, qualifiers)\ | |
pre_qualifiers int name(float, double) qualifiers { return 42; } | |
#else | |
static_assert(false, "Name collision with test macro"); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "signature.hpp" | |
struct Foo { | |
SIGNATURE_TEST_METHOD(, method,); | |
SIGNATURE_TEST_METHOD(, lref_method, &); | |
SIGNATURE_TEST_METHOD(, rref_method, &&); | |
SIGNATURE_TEST_METHOD(, const_method, const); | |
SIGNATURE_TEST_METHOD(, const_lref_method, const &); | |
SIGNATURE_TEST_METHOD(, const_rref_method, const &&); | |
SIGNATURE_TEST_METHOD(, const_noexcept_method, const noexcept); | |
SIGNATURE_TEST_METHOD(, const_lref_noexcept_method, const & noexcept); | |
SIGNATURE_TEST_METHOD(, const_rref_noexcept_method, const && noexcept); | |
SIGNATURE_TEST_METHOD(, const_volatile_method, const volatile); | |
SIGNATURE_TEST_METHOD(, const_volatile_lref_method, const volatile &); | |
SIGNATURE_TEST_METHOD(, const_volatile_rref_method, const volatile &&); | |
SIGNATURE_TEST_METHOD(, volatile_method, volatile); | |
SIGNATURE_TEST_METHOD(, volatile_lref_method, volatile &); | |
SIGNATURE_TEST_METHOD(, volatile_rref_method, volatile &&); | |
SIGNATURE_TEST_METHOD(, noexcept_method, noexcept); | |
SIGNATURE_TEST_METHOD(, lref_noexcept_method, & noexcept); | |
SIGNATURE_TEST_METHOD(, rref_noexcept_method, && noexcept); | |
SIGNATURE_TEST_METHOD(, volatile_noexcept_method, volatile noexcept); | |
SIGNATURE_TEST_METHOD(, volatile_lref_noexcept_method, volatile & noexcept); | |
SIGNATURE_TEST_METHOD(, volatile_rref_noexcept_method, volatile && noexcept); | |
SIGNATURE_TEST_METHOD(, const_volatile_noexcept_method, const volatile noexcept); | |
SIGNATURE_TEST_METHOD(, const_volatile_lref_noexcept_method, const volatile & noexcept); | |
SIGNATURE_TEST_METHOD(, const_volatile_rref_noexcept_method, const volatile && noexcept); | |
SIGNATURE_TEST_METHOD(static, static_method,); | |
SIGNATURE_TEST_METHOD(static, static_noexcept_method,noexcept); | |
}; | |
#undef SIGNATURE_TEST_METHOD | |
#ifndef SIGNATURE_TEST | |
#define SIGNATURE_TEST(name, is_const, is_noexcept, is_volatile, is_pure, is_lref, is_rref) \ | |
namespace _##name##_test { \ | |
using Type = Signature<decltype(&Foo::name)>; \ | |
static_assert(std::is_same_v<typename Type::Ret, int>); \ | |
static_assert(is_pure || std::is_same_v<typename Type::Class, Foo>); \ | |
static_assert(std::is_same_v<typename Type::Args, std::tuple<float, double>>); \ | |
static_assert(is_const == Type::Const); \ | |
static_assert(is_noexcept == Type::Noexcept); \ | |
static_assert(is_volatile == Type::Volatile); \ | |
static_assert(is_pure == Type::Pure); \ | |
static_assert(is_lref == Type::LRef); \ | |
static_assert(is_rref == Type::RRef); \ | |
} | |
#else | |
static_assert(false, "Name collision with test macro"); | |
#endif | |
// static functions | |
SIGNATURE_TEST(static_method, false, false, false, true, false, false); | |
SIGNATURE_TEST(static_noexcept_method, false, true, false, true, false, false); | |
// methods const noexcept volat pure lref rref | |
SIGNATURE_TEST(method, false, false, false, false, false, false); | |
SIGNATURE_TEST(lref_method, false, false, false, false, true, false); | |
SIGNATURE_TEST(rref_method, false, false, false, false, false, true); | |
SIGNATURE_TEST(const_method, true, false, false, false, false, false); | |
SIGNATURE_TEST(const_lref_method, true, false, false, false, true, false); | |
SIGNATURE_TEST(const_rref_method, true, false, false, false, false, true); | |
SIGNATURE_TEST(noexcept_method, false, true, false, false, false, false); | |
SIGNATURE_TEST(lref_noexcept_method, false, true, false, false, true, false); | |
SIGNATURE_TEST(rref_noexcept_method, false, true, false, false, false, true); | |
SIGNATURE_TEST(volatile_method, false, false, true, false, false, false); | |
SIGNATURE_TEST(volatile_lref_method, false, false, true, false, true, false); | |
SIGNATURE_TEST(volatile_rref_method, false, false, true, false, false, true); | |
SIGNATURE_TEST(const_noexcept_method, true, true, false, false, false, false); | |
SIGNATURE_TEST(const_lref_noexcept_method, true, true, false, false, true, false); | |
SIGNATURE_TEST(const_rref_noexcept_method, true, true, false, false, false, true); | |
SIGNATURE_TEST(const_volatile_method, true, false, true, false, false, false); | |
SIGNATURE_TEST(const_volatile_lref_method, true, false, true, false, true, false); | |
SIGNATURE_TEST(const_volatile_rref_method, true, false, true, false, false, true); | |
SIGNATURE_TEST(volatile_noexcept_method, false, true, true, false, false, false); | |
SIGNATURE_TEST(volatile_lref_noexcept_method, false, true, true, false, true, false); | |
SIGNATURE_TEST(volatile_rref_noexcept_method, false, true, true, false, false, true); | |
SIGNATURE_TEST(const_volatile_noexcept_method, true, true, true, false, false, false); | |
SIGNATURE_TEST(const_volatile_lref_noexcept_method, true, true, true, false, true, false); | |
SIGNATURE_TEST(const_volatile_rref_noexcept_method, true, true, true, false, false, true); | |
#undef SIGNATURE_TEST |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment