C ++中是否有办法反映变量的“指针级别数”(例如,int* a
为1级,int** b
为2级,{{1是0级)
..除了使用int c
并解析出来的字符串?
我问的原因是我正在使用pointers to member functions,我需要知道是否在编译时调用成员函数typeid
或obj->func()
。
答案 0 :(得分:4)
如果obj
是T**
,则obj.*foo
的格式不正确。所以你只需要弄清楚它是指针还是非指针。你可以使用重载。
template<typename T, typename M> void f(T *obj, M m) { // pointer
(obj->*m)();
}
template<typename T, typename M> void f(T &obj, M m) { // not a pointer
(obj.*m)();
}
这样做的缺点是它只适用于零参数成员函数指针,并且它不会返回这些函数返回的值(如果有的话)。您不能执行以下操作(可以轻松实现),因为两个分支都将进行类型检查
if(is_pointer(obj)) v = (obj->*m)(arg...); else v = (obj.*m)(args...);
所做的只是调用一个函数来取消引用你的对象,如果它是一个指针
template<typename T> T &deref(T *t) { return *t; }
template<typename T> T &deref(T &t) { return t; }
然后你可以说
v = (deref(obj).*m)(args...);
答案 1 :(得分:3)
部分模板专业化将很容易告诉你:
template<typename T>
struct PtrLevel
{
enum { value = 0 };
};
template<typename TTarget>
struct PtrLevel<TTarget*>
{
enum { value = PtrLevel<TTarget>::value + 1 };
};
在C ++ 0x中,您可以使用decltype
和SFINAE来处理智能指针,使其报告为具有非零指针级别。
答案 2 :(得分:3)
您可以使用TR1中std::is_pointer
标头中的type_traits
(使用部分特化来产生答案),但使用重载解析可能更简单。
这是一个例子,假设返回void,没有参数,并且不需要处理多个间接层:
template <typename T, typename F>
inline void invoke(T& obj, F func)
{
(obj.*func)();
}
template <typename T, typename F>
inline void invoke(T* obj, F func)
{
(obj->*func)();
}
如果您需要处理多个间接级别,可以用以下代码替换第二个函数:
template <typename T, typename F>
inline void invoke(T* obj, F func)
{
invoke(*obj, func);
}
这将以递归方式剥离间接级别,直到您最终得到可以调用成员函数的内容。
答案 3 :(得分:2)
拯救的一些模板魔法:
template<typename T>
struct Depth { enum DepthEnum { value = 0 };};
template<typename T>
struct Depth<T*> { enum DepthEnum{ value = Depth<T>::value +1 };};
template<typename T>
size_t getDepth(T const& o)
{
return Depth<T>::value;
}
int main()
{
int a0;
int* a1;
int** a2;
int*** a3;
int**** a4;
int***** a5;
int****** a6;
std::cout << getDepth(a0) << std::endl;
std::cout << getDepth(a1) << std::endl;
std::cout << getDepth(a2) << std::endl;
std::cout << getDepth(a3) << std::endl;
std::cout << getDepth(a4) << std::endl;
std::cout << getDepth(a5) << std::endl;
std::cout << getDepth(a6) << std::endl;
}
输出:
> g++ test.cpp
> ./a.out
0
1
2
3
4
5
6
回到你想要它的原因。这似乎有点怀疑。您的编译器已经知道在编译时起诉的版本。记住C ++对它的输入非常严格,这个信息在编译时是已知的,因此如果你使用了错误的版本,你将会遇到编译器错误。
答案 4 :(得分:0)
我不知道有任何内置方法可以做到这一点,但你可以实现一个模拟“计数指针”的小模板类,你可以很容易地确定你的“指针深度”:
template <typename T> class Ptr {
private:
T* ptr;
int d;
public:
// overload all meaningful operators, like * etc.
// e.g.
T& operator*() {
return *T;
}
int depth() const {
return d;
}
}
答案 5 :(得分:0)
只要您的指针有效,您就可以使用以下代码:它将为您传递给它的对象提供参考级别(只需稍加更改即可更改它以返回对象指针引用,只需使用注释而不是acual代码并直接使用countPartial):
template <class T> int countPartial(T *x,int depth)
//use template <class T> T& countPartial(T *x)
{
return countPartial(*x,depth+1);
//return countPartial(*x);
}
template <class T> int countPartial(T &x,int depth)
//use template <class T> T& countPartial(T &x)
{
return depth;
//return x;
}
template <class T> int count(T x)
{
return countPartial(x,0);
}
答案 6 :(得分:-1)
可能这个糟糕的解决你的麻烦 T是模板。 funcptr ptr功能。
int callfunc( T ptr)
{
depth = 0;
if ( typeof(ptr)!= typeof(funcptr))
{
depth++;
depth = depth + callfunc(*ptr);
}
return depth;
}