...メンバー関数へのポインターは奇妙な動物ですが?
C++ クラスを Lua にバインドするライブラリをコーディングしています。特定の型オブジェクトを Lua スタックにプッシュする (そしてそれらを void* にキャストする) ことによって引き起こされる型消去に対処する必要があります。このため、さまざまな種類のデータ (非 const および const オブジェクト、非 const および const メンバー、および将来的には volatile および non volatile のすべてを 2 倍にするなど) のさまざまなテンプレートの過剰な増殖を避けるために、私は管理します。特定のフラグを設定するだけで、実行時に Lua にバインドされたオブジェクトの constness。
今、私はメンバー関数へのポインターを扱っています。これまでの設計に従って、const メンバー関数へのポインターを非 const メンバー関数に安全にキャストし、同じテンプレートを非 const に再利用し、前述のフラグを使用して実行時に constness を処理できれば幸いです。
しかし、これが本当に可能かどうか疑問に思う別のヒントがあります。以下のコードを検討してください。
#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
、他のタイプに安全にキャスト (または少なくとも) できるようです (意味がある場合)。
それで、ステップの1つで私の推論はひどく間違っていますか、それともコンパイラに関係なくこれを行うことができますか? const メンバ関数へのポインタで同じようにプレイできますか?