2012-04-08 5 views
1

...でもpointers to member functions are strange animalsですか?私はconstメンバへのポインタを同じ型であるが非const型に安全にキャストできますか?

私はC++クラスをLuaにバインドするライブラリをコーディングしています。私は特定の型のオブジェクトをLuaスタックにプッシュすることによって引き起こされる型の消去に対処しなければなりません(そしてそれらをvoid *にキャストします)。このため、さまざまな種類のデータ(非constおよびconstオブジェクト、非constおよびconstメンバー、将来的には揮発性および不揮発性の2倍のすべて)の異なるテンプレートの過度の拡散を避けるために、実行時に特定のフラグを設定するだけで、Luaにバインドされたオブジェクトのconstness。

ここでは、メンバー関数のポインタを扱っています。これまでの私の設計では、constメンバ関数へのポインタを非constのものに安全にキャストしてからnon-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" 
} 

それはとてもそのかかわらずthese animals can even change their own size、特定の状況では、あなたが安全にキャストすることができます(あるいは、少なくとも、const_cast)と思われる彼らは、他のタイプに(彼らは理にかなっている場合)。

コンパイラに関係なく、私の推論はひどく間違っていますか? constメンバ関数へのポインタを使って同じ方法で再生できますか?

答えて

2

"非const"特殊化では、FTは単にconst修飾子を含むように推測されます。それはそれはちょうどに渡された、消えない

はこれを試してみてください:。

template<typename Class, typename FT> struct tmpl<FT(Class::*)>{ 
    static void f(){ 
     if (std::is_const<FT>::value) { 
      cout<<"const as non const"<<endl; 
     } else { 
      cout<<"non const"<<endl; 
     } 
    } 
}; 

http://ideone.com/g2Eie

をあなたはconstを殺したい場合は、const_castは仕事のための唯一の実行可能なツールです。

+1

meh、私はまだこのテンプレート機械を習得していません。 –

+0

2番目の質問で私を手伝ってもらえますか?constメンバ関数へのポインタと同じ方法で再生できますか?今は不変性は何にも(右か?)含まれていません。しかし、実行時にあなた自身で管理する場合は、 'void(A :: f)()const'を' void(A :: f)() 'にキャストすることは、とにかく安全ですか? –

+0

@LorenzoPistone 'const'修飾子が暗黙の' this'パラメータに適用され、キャストが関数パラメータの型を変更することができないので、メンバ関数はキャストできません。うまくいけば、これはそのような問題ではなく、あなたは正規の引数リストのパラメータの修飾と同様に対処することができます。 – Potatoswatter

関連する問題