检查两个函数或成员函数指针的签名是否相等
Check that signature of two functions or member function pointer equal
我写了一些代码来检查自由函数的签名是否等于成员函数的签名等。它比较提取的 return 类型和函数参数:
#include <tuple>
#include <type_traits>
template<class Signature>
struct signature_trait;
template<class R, class... Args>
struct signature_trait<R(Args...)>
{
using return_type = R;
using arg_types = std::tuple<Args...>;
};
template<class R, class... Args>
struct signature_trait<R(*)(Args...)>
{
using return_type = R;
using arg_types = std::tuple<Args...>;
};
template<class R, class U, class... Args>
struct signature_trait<R(U::*)(Args...)>
{
using return_type = R;
using arg_types = std::tuple<Args...>;
};
template<class Signature>
using signature_trait_r = typename signature_trait<Signature>::return_type;
template<class Signature>
using signature_trait_a = typename signature_trait<Signature>::arg_types;
template<class Signature1, class Signature2>
using is_same_signature =
std::conjunction<
std::is_same<signature_trait_r<Signature1>, signature_trait_r<Signature2>>,
std::is_same<signature_trait_a<Signature1>, signature_trait_a<Signature2>>
>;
template<class Signature1, class Signature2>
inline constexpr bool is_same_signature_v =
is_same_signature<Signature1, Signature2>::value;
struct Foo
{
void bar(int, int){}
};
void bar(int, int){}
int main()
{
static_assert(is_same_signature_v<decltype(&bar), decltype(&Foo::bar)>, "");
static_assert(is_same_signature_v<decltype(&bar), void(int, int)>, "");
static_assert(is_same_signature_v<decltype(&Foo::bar), void(int, int)>, "");
static_assert(is_same_signature_v<decltype(&Foo::bar), void(Foo::*)(int, int)>, "");
}
效果很好,但是可以简化吗?也许在某些情况下此解决方案不起作用?
为了简单起见:没有理由将 return_type
和 arg_types
分开:您可以将它们合并为一个 std::tuple
,其中 return_type
在第一位。
#include <tuple>
#include <type_traits>
template<class Signature>
struct signature_trait;
template<class R, class... Args>
struct signature_trait<R(Args...)>
{ using type = std::tuple<R, Args...>; };
template<class R, class... Args>
struct signature_trait<R(*)(Args...)>
{ using type = std::tuple<R, Args...>; };
template<class R, class U, class... Args>
struct signature_trait<R(U::*)(Args...)>
{ using type = std::tuple<R, Args...>; };
template<class Signature>
using signature_trait_t = typename signature_trait<Signature>::type;
template<class Signature1, class Signature2>
using is_same_signature = std::is_same<signature_trait_t<Signature1>,
signature_trait_t<Signature2>>;
template<class Signature1, class Signature2>
inline constexpr bool is_same_signature_v =
is_same_signature<Signature1, Signature2>::value;
struct Foo
{ void bar (int, int) {} };
void bar (int, int) {}
int main ()
{
static_assert(is_same_signature_v<decltype(&bar), decltype(&Foo::bar)>, "");
static_assert(is_same_signature_v<decltype(&bar), void(int, int)>, "");
static_assert(is_same_signature_v<decltype(&Foo::bar), void(int, int)>, "");
static_assert(is_same_signature_v<decltype(&Foo::bar), void(Foo::*)(int, int)>, "");
}
我写了一些代码来检查自由函数的签名是否等于成员函数的签名等。它比较提取的 return 类型和函数参数:
#include <tuple>
#include <type_traits>
template<class Signature>
struct signature_trait;
template<class R, class... Args>
struct signature_trait<R(Args...)>
{
using return_type = R;
using arg_types = std::tuple<Args...>;
};
template<class R, class... Args>
struct signature_trait<R(*)(Args...)>
{
using return_type = R;
using arg_types = std::tuple<Args...>;
};
template<class R, class U, class... Args>
struct signature_trait<R(U::*)(Args...)>
{
using return_type = R;
using arg_types = std::tuple<Args...>;
};
template<class Signature>
using signature_trait_r = typename signature_trait<Signature>::return_type;
template<class Signature>
using signature_trait_a = typename signature_trait<Signature>::arg_types;
template<class Signature1, class Signature2>
using is_same_signature =
std::conjunction<
std::is_same<signature_trait_r<Signature1>, signature_trait_r<Signature2>>,
std::is_same<signature_trait_a<Signature1>, signature_trait_a<Signature2>>
>;
template<class Signature1, class Signature2>
inline constexpr bool is_same_signature_v =
is_same_signature<Signature1, Signature2>::value;
struct Foo
{
void bar(int, int){}
};
void bar(int, int){}
int main()
{
static_assert(is_same_signature_v<decltype(&bar), decltype(&Foo::bar)>, "");
static_assert(is_same_signature_v<decltype(&bar), void(int, int)>, "");
static_assert(is_same_signature_v<decltype(&Foo::bar), void(int, int)>, "");
static_assert(is_same_signature_v<decltype(&Foo::bar), void(Foo::*)(int, int)>, "");
}
效果很好,但是可以简化吗?也许在某些情况下此解决方案不起作用?
为了简单起见:没有理由将 return_type
和 arg_types
分开:您可以将它们合并为一个 std::tuple
,其中 return_type
在第一位。
#include <tuple>
#include <type_traits>
template<class Signature>
struct signature_trait;
template<class R, class... Args>
struct signature_trait<R(Args...)>
{ using type = std::tuple<R, Args...>; };
template<class R, class... Args>
struct signature_trait<R(*)(Args...)>
{ using type = std::tuple<R, Args...>; };
template<class R, class U, class... Args>
struct signature_trait<R(U::*)(Args...)>
{ using type = std::tuple<R, Args...>; };
template<class Signature>
using signature_trait_t = typename signature_trait<Signature>::type;
template<class Signature1, class Signature2>
using is_same_signature = std::is_same<signature_trait_t<Signature1>,
signature_trait_t<Signature2>>;
template<class Signature1, class Signature2>
inline constexpr bool is_same_signature_v =
is_same_signature<Signature1, Signature2>::value;
struct Foo
{ void bar (int, int) {} };
void bar (int, int) {}
int main ()
{
static_assert(is_same_signature_v<decltype(&bar), decltype(&Foo::bar)>, "");
static_assert(is_same_signature_v<decltype(&bar), void(int, int)>, "");
static_assert(is_same_signature_v<decltype(&Foo::bar), void(int, int)>, "");
static_assert(is_same_signature_v<decltype(&Foo::bar), void(Foo::*)(int, int)>, "");
}