2012-04-04 19 views
1

コンパイル時に2つの実行時コードパスのいずれかを決定する方法はありますか?私は関数のオーバーロードがこの偉業を達成するために使用できることを認識していますが、私の関数の両方がコンパイルされ、プログラムにリンクされているのでコードサイズが大きくなります。このサイズのオーバーヘッドを避ける方法はありますか?コンパイル時の条件付き実行時文

基本的に、私は何をしたいです:

#include <boost/mpl/if.hpp> 
#include <boost/type_traits/is_abstract.hpp> 

template <class T> 
    class X 
{ 
    public: 
     void copy_t(T &old_t) 
     { 
      // 
      // if T is abstract, (meaning that t is a pointer) 
      // 
      t = old_t.clone(); 

      // 
      // else 
      // 
      t = old_t; 
     } 

    private: 
     typename boost::mpl::if_<boost::is_abstract<T>, T *, T>::type t; 
}; 

私が知っている唯一の方法は、必要とするオーバーロードされたメンバ関数:

template <class T> 
    class X 
{ 
    public: 
     void copy_t(T &old_t) 
     { 
      t = make_copy(old_t, t); 
     } 

    private: 
     T *make_copy(T &old_t, T *t) 
     { 
      return old_t.clone(); 
     } 

     T &make_copy(T &old_t, T &t) 
     { 
      return old_t; 
     } 

     typename boost::mpl::if_<boost::is_abstract<T>, T *, T>::type t; 
}; 

しかし、今、2つのmake_copyメンバ関数は、にコンパイルとリンクされていますたとえXが抽象クラステンプレートパラメータでインスタンス化されることがありますが、その場合はそのうちの1つだけが必要です。

+0

オプティマイザは未コール関数を削除しませんか? – Nick

+2

私はこれを明確にしましょう:最終実行ファイルの1ライナー関数の追加コストが心配ですか? –

+0

また、コードではかなりの前提があることに注意してください。たとえば、非抽象型のすべてのオブジェクトは完全なオブジェクトです。私。異なった非抽象型を拡張する型があり、関数が中間型で呼び出された場合は、スライスします。あなたのインタフェースは、*お約束(コピー/クローンのいずれか)の場合に最善を尽くすものを提供するように見えますが、その後必ずしも約束を果たしているとは限りません。 –

答えて

3

例からは、関数がクラス テンプレートのメンバーであるように見えます。その場合は、実際には が使用されている場合にのみインスタンス化されます。過負荷の解決が常にそのうちの1つを選択すると、もう1つは はインスタンス化されません。

これは、多くのメタプログラミング技術の重要なルールです。インスタンス化されていない関数が の場合、コンパイル時にエラーが発生する場合は、 はまれです。