是否可以从其地址(不是来自成员函数类型)获取成员函数(例如类类型或返回类型)的组成部分?
例如给出
class foo
{
int bar()
{
return 5;
}
};
我喜欢
is_same< function_types<&foo::bar>::class_type, foo>::value == true;
我还知道成员函数有一个像R (C::*)()
这样的签名,即没有参数,也没有cv资格。
谢谢。
答案 0 :(得分:3)
您可以在模板函数中捕获类型:
#include <iostream>
struct foo {
foo() { std::cout << "OK\n"; }
int bar() {return 0;}
};
template<typename C, typename R>
bool thing(R (C::*)()) {
C x;
}
int main() {
thing(&foo::bar);
}
打印“确定”,这样您就可以将is_same
支票放入其中。我真的不确定问题是什么 - 显然我们 使用成员函数的类型进行模板参数推导。
如果你以某种方式无效地reinterpret_cast
成员函数指向别的东西,以便丢弃它的类型,那么你就无法恢复它。
如果您已将成员函数指针转换为兼容的成员函数指针类型,例如R (B::*)()
- &gt; R (D::*)()
,其中B是D的基类,那么我认为你可以使用dynamic_cast
来测试它是否真的是一个B函数。您无法以这种方式恢复类型,只能恢复成员函数指针的typeid
,因为它是运行时操作。类型实际上只存在于C ++的编译时,因此没有办法“获取”值的动态类型,无论该值是成员函数指针还是其他任何值。编译器要么知道它,要么不知道,如果确实如此,那么实际上使用该类型的组成部分会有各种模板技巧。
答案 1 :(得分:2)
不。这是所谓的运行时反射的一部分,在C ++这样的低级语言中是不可能的。您无法仅从地址获取此数据。
无论你在做什么,在C ++中你都可以使用元编程方法,使用模板魔法或预处理器魔法来做到这一点。例如,Boost库依赖于这种方法。
答案 2 :(得分:1)
在C ++之前的0x中,你不能很容易地做到这一点。在C ++ 0x中,您可以使用模板函数和decltype的组合来执行此操作:
template <typename R> struct unary_function_info { typedef R result_type; typedef void class_type; };
template <typename R> unary_function_info get_function_info(R (*)());
template <typename C, typename R> struct unary_member_function_info { typedef R result_type; typedef C class_type; };
template <typename C, typename R> unary_member_function_info get_function_info(R (C::*)());
is_same<decltype(get_function_info(&foo::bar))::class_type, foo>::value == true;
然后根据需要将上述内容扩展为高度优化。
答案 3 :(得分:0)
您可以使用重载:
void F(int);
void F(bool);
F(foo.bar());
您可以使用模板功能和部分专业化来获得更通用的解决方案。
答案 4 :(得分:0)
struct char2_t { char xxx[2]; };
template <bool flag, typename T, typename U> struct select { typedef T type; };
template <typename T, typename U> struct select<false, T, U> { typedef U type; };
template<class Foo, class C, class R>
typename select<boost::is_same<Foo, C>::value, char, char2_t>::type test(R (C::*)());
void check_in_this_function() {
char check_arr1[ sizeof(test<foo>(&foo::bar))==1 ? 1 : -1];
char check_arr2[ sizeof(test<int>(&foo::bar))==1 ? 1 : -1]; // error: negative subscript
}
答案 5 :(得分:0)
如果由于某种原因您将成员函数指针作为简单类型传递,则可以使用以下内容获取组成部分。 (这需要C ++ 0x,在当前的C ++中,它支持任意arities将需要更多的工作。)
#include <tuple>
template <class T>
struct method_traits;
template <class ReturnType, class ObjectType, class... ArgTypes>
struct method_traits<ReturnType (ObjectType::*)(ArgTypes...)>
{
typedef ReturnType result_type;
typedef ObjectType object_type;
template <unsigned N>
struct argument
{
typedef typename std::tuple_element<N - 1, std::tuple<ArgTypes...>>::type type;
};
};
template <class ReturnType, class ObjectType, class... ArgTypes>
struct method_traits<ReturnType (ObjectType::*)(ArgTypes...) const>
{
typedef ReturnType result_type;
typedef ObjectType object_type;
template <unsigned N>
struct argument
{
typedef typename std::tuple_element<N - 1, std::tuple<ArgTypes...>>::type type;
};
};
struct Foo
{
int bar(double, float) const ;
};
template <class MemberFun>
void test(MemberFun f)
{
typename method_traits<MemberFun>::result_type result;
typename method_traits<MemberFun>::object_type object;
typename method_traits<MemberFun>::template argument<1>::type i = 10; //:)
result = (object.*f)(i, 2.0f);
}
int main()
{
test(&Foo::bar);
}