2016-12-30 6 views
2

私は最近、効率性と安全性の理由から、特に多型ではないテンプレートクラスを設計していたC++ライブラリに取り組んでいました。後で私がこれを忘れずに、すべてを間違って壊すことを防ぐために、私は良い市民であり、その効果を静的な主張に加えると思った。テンプレートクラスがポリモーフィックでないことを確認しますか?

私が最初にこのような何か試してみました:

template <typename T> class VirtualVerboten { 
    ... 

    static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
        "This should not be polymorphic."); // Error! 
}; 

私はVirtualVerbotenを使用している時に、それは不完全なタイプですが、これはコンパイルされませんが。これは、非テンプレートクラスだったら、私はちょうど右のタイプの後static_assertを置くところ:

class NonTemplateVirtualVerboten { 
    ... 
} 
static_assert(!std::is_polymorphic<NonTemplateVirtualVerboten>::value, 
       "This should not be polymorphic."); 

をしかし、これはテンプレートクラスであることから、「テンプレートstatic_assert」を作るの類似したアイデアは法的ではありません:私が思いついた

template <typename T> class VirtualVerboten { 
    ... 

}; 

template <typename T>    
static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
       "This should not be polymorphic."); // Error! 

ソリューションは、おそらくテンプレートが(具体的には、コンストラクタ)インスタンス化されたとき、そこに静的アサーションを入れて使用されるVirtualVerbotenの内部メンバ関数を見つけることだった。

template <typename T> class VirtualVerboten { 
    VirtualVerboten(); 
}; 

template <typename T> 
VirtualVerboten<T>::VirtualVerboten() { 
    static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
       "This should not be polymorphic."); // Yay! 
    doSomeActualThingsAtRuntime(); 
} 

この特定のコンストラクタが実際に呼び出され、インスタンス化されるということを除いて、これは機能します。これは、呼び出すことができるコンストラクタが複数ある場合に失敗します。

ここにこの静的アサーションを追加する「確実な方法」はありますか?なぜ元のコードがエラーを生成していたのか、そしてテンプレート静的アサーションを使用できない理由を理解しています。これは、「これを行う別の方法がありませんでしたか? 「あなたがしたことがうまくいかない理由はここにあります。

+0

うう:


IMO、別のエレガントな方法は、次のような、&は同じ継承するユーティリティクラスを作成するのですか?コンストラクタ?どういうわけか、クラスをどこかに構築しなければなりません。あなたの静的な主張を押してください。 –

+0

@SamVarshavchikそれは私がやったことです。おそらく私は質問を編集して、それをもっと明確にするべきです。 – templatetypedef

+0

静的アサーションは2番目のフェーズでのみチェックされるように、型を依存関係にパッケージ化するだけで済みます。 –

答えて

3

すでに@JerryCoffin's commentで示されています。最も良い方法は、デストラクタでstatic_assertを使用することです。すなわち

template <typename T> 
class VirtualVerboten { 
public: 
    ~VirtualVerboten() { 
    static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
        "This should not be polymorphic."); 
    } 
}; 

デストラクタが唯一の1にすることができるのでは、そのオブジェクトのインスタンスがあるたびstatic_assertがチェックされていることを保証しています。

template<typename T> 
struct NonPolymorphic 
{ 
    ~NonPolymorphic() 
    { static_assert(!std::is_polymorphic<T>::value, "This should not be polymorphic."); } 
}; 

template <typename T> 
class VirtualVerboten : NonPolymorphic<VirtualVerboten<T>> 
{ 
    // ... 
}; 
0

キーワードfinalは、クラスが継承されないようにするC++ 14の機能です。クラスが継承されている場合、コードはコンパイルされません。例:コンパイラは文句を言う

template <typename T> 
class VirtualVerboten final { 
    ... 
} 

誰もがそれを継承しようとすると...

class Derived : public VirtualVerboten<int> { 
    ... 
} 

+1

質問は相続ではなく、多型についてです。本当の2つは非常に密接に関連していますが、ポリモーフィズムのない継承(つまり仮想関数の使用)も可能です。 cppreferenceは 'is_polymorphic'型の特性を'少なくとも一つの仮想関数を宣言または継承する非共用体クラス 'として記述します。これは、OPが除外しようとしているクラスのタイプについてのヒントを与えるはずです。 –

+0

奇妙なことに、私が検討しているケースでは継承を使用しますが、多型を使用しないでください。このアプローチは私の場合は実際には機能しません。 – templatetypedef

関連する問題