存储或反射变量的"reference level"
Store or reflect on the "reference level" of a variable
C++中是否有一种方法可以反映变量的"指针级别数"(例如,int* a
是1级,int** b
是2级,而int c
是0级)
除了使用typeid
并解析由此产生的字符串之外?
我之所以这么问,是因为我正在使用指向成员函数的指针,并且我需要知道在编译时是将成员函数调用为obj->func()
还是obj.func()
。
如果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...);
您可以从TR1中的type_traits
标头中使用std::is_pointer
(它使用部分专用化来生成答案),但只使用重载解析可能更简单。
这里有一个例子,假设返回无效,没有参数,并且不需要处理多个间接级别:
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);
}
这将递归地剥离间接级别,直到您最终得到可以在上调用成员函数的东西。
部分模板专业化将很容易告诉您:
template<typename T>
struct PtrLevel
{
enum { value = 0 };
};
template<typename TTarget>
struct PtrLevel<TTarget*>
{
enum { value = PtrLevel<TTarget>::value + 1 };
};
演示:http://ideone.com/ZPH8X
在C++0x中,您可能会使用decltype
和SFINAE来处理智能指针,这样它们就会被报告为具有非零指针级别。
一点模板魔术拯救:
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++对其类型非常严格,并且这些信息在编译时是已知的,因此如果您使用了错误的版本,则会出现编译器错误。
我不知道有任何内置的方法可以做到这一点,但你可以实现一个模拟"计数指针"的小模板类,这样你就可以很容易地确定你的"指针深度":
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;
}
}
只要你的指针是有效的,你就可以使用以下代码:它会给你传递给它的对象提供引用级别(只需做一点更改,你可以将其更改为返回指针引用的对象,只需使用注释而不是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);
}
这可能会解决您的问题T是模板。funcptr函数的ptr。
int callfunc( T ptr)
{
depth = 0;
if ( typeof(ptr)!= typeof(funcptr))
{
depth++;
depth = depth + callfunc(*ptr);
}
return depth;
}
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- Visual Studio Code "undefined reference to `WinMain@16'"
- 使用 MATLAB 编码器生成C++代码:编译错误"undefined reference to `rgb2gray_tbb_real64'"
- 使用 [] 运算符时"binding reference of type discards qualifiers"
- 为什么创建友元类的实例会导致"undefined reference to"错误?
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 这对"With a stackless coroutine, only the top-level routine may be suspended."意味着什么
- Tensorflow c++ api undefined reference to 'tflite::D efaultErrorReporter()'
- 不断"Attempting to reference a deleted function"
- std::iterator::reference 必须是引用吗?
- C++/SDL "initial value of reference to a non-const must be an lvalue"
- 为什么在使用 SDL2 时仍然收到'undefined reference'链接器错误?
- OpenCV undefined reference to 'cv::imread(cv::String const&, int)'
- Libcurl c++ "undefined reference to" (Windows/MinGW/g++)
- C++返回类型 T(&)[] 与使用 reference = T(&)[] 作为返回类型
- const auto & 和 auto & if reference 对象之间的区别是 const
- 尝试使用 extern "C" 调用 C 中的C++方法,得到"undefined reference to"对象的链接器错误
- 以前的'namespace reference { }'声明
- build error : undefined reference to `yyFlexLexer::yyFlexLex
- 存储或反射变量的"reference level"