...即使指向成员函数的指针是奇怪的动物?
我正在编写一个库来将 C++ 类绑定到 Lua。我必须处理将某些类型对象推入 Lua 堆栈(并将它们强制转换为 void*)而导致的类型擦除。出于这个原因,也是为了避免针对不同类型的数据(非 const 和 const 对象、非 const 和 const 成员,以及将来将 volatile 和 non volatile 的所有内容加倍......)的不同模板过度增殖,我管理通过简单地设置某个标志,在运行时绑定到 Lua 的对象的常量。
现在,我正在处理指向成员函数的指针。到目前为止,按照我的设计,如果我可以安全地将指向 const 成员函数的指针转换为非常量,然后为非常量重用相同的模板,并在运行时使用上述标志处理常量,我会很高兴。
但还有另一个提示让我怀疑这是否真的可能。考虑下面的代码:
#include <iostream>
#include <typeinfo>
using namespace std;
struct A{
const int a;
int b;
};
template<typename T> struct tmpl;
template<typename Class, typename FT> struct tmpl<FT(Class::*)>{
static void f(){
cout<<"non const"<<endl;
}
};
//Try commenting this out, code compiles, both A::a and A::b instantiate the first template
template<typename Class, typename FT> struct tmpl<const FT(Class::*)>{
static void f(){
cout<<"const"<<endl;
}
};
int main(){
cout<<typeid(&A::a).name()<<endl; //prints "M1AKi"
tmpl<decltype(&A::a)>::f(); //prints "const"
cout<<typeid(&A::b).name()<<endl; //prints "M1Ai"
tmpl<decltype(&A::b)>::f(); //prints "non const"
//Let's do what it seems that can be done implicitly (providing only one template specialization) in an explicit way
int(A::*memb)=(int(A::*))&A::a;
cout<<typeid(memb).name()<<endl; //prints "M1Ai"
tmpl<decltype(memb)>::f(); //prints "non const"
}
似乎无论这些动物甚至可以改变自己的大小,在某些情况下,您都可以安全地(或至少const_cast
)将它们转换为其他类型(如果它们有意义的话)。
那么,我的推理在其中一个步骤中是否存在严重错误,或者我可以这样做,而不管编译器如何?我可以用指向 const 成员函数的指针以同样的方式玩吗?