3

テンプレート クラス/構造体の本体内に、部分的に特殊化されたテンプレート関数を記述しようとしています。部分的な特殊化は、再帰的なテンプレート メタプログラミングを実行するために行われます。

template<size_t N>
struct my_class {

template<size_t D> double my_func(...){}

template<> double my_func<0>(...){}

double other_func(...){ return my_func<N-1>(...); }
};

しかし、g++ ( -std=c++0xオプションを使用) は、クラス/構造体内でテンプレート関数を部分的に特殊化できないと文句を言い、テンプレート関数my_funcを別の名前空間でクラス スコープの外に書くように強制します。静的であり、最終的にすべてのプライベートクラス変数を渡し、コードを非常に面倒なものにします ( thisによって簡単に参照されるすべてのメンバー変数)。

部分的なテンプレートの特殊化 (関数をmy_classのプライベート サブクラスの静的メンバーとしても作成できます) と同じクラス内でのメタプログラミングを行う方法はありますか?

これにより、コードがよりクリーンになり、保守が大幅に容易になります。Ubuntu 12.04 と gcc 4.6 を使用しています。

乾杯

4

1 に答える 1

4

enable_if関数をオーバーロードし (特殊化しない) 、オーバーロードのいずれかのみを選択的に有効にするために使用することで、目的の結果を得ることができます。

template<size_t D> typename std::enable_if<D!=0, double>::type my_func(...){}

template<size_t D> typename std::enable_if<D==0, double>::type my_func(...){}

enable_if制約とは、D!=0最初のオーバーロードのみが実行可能な関数でありD==0、2 番目のオーバーロードのみが実行可能な関数であることを意味します。

C++03 では、 で同じことができますboost::enable_if_c

私の好ましい解決策は、醜いenable_if使用法をカスタム特性タイプに置き換えることです。おそらく次のようなものです。

template<size_t> struct if_zero { typedef double disable; };
template<> struct if_zero<0> { typedef double enable; };

template<size_t D> typename if_zero<D>::disable my_func(...){}
template<size_t D> typename if_zero<D>::enable  my_func(...){}

これは同じ効果がありますが、よりリテラシーなプログラミングスタイルになります。

さらに読みやすい別のフォームは次のとおりです。

template<bool, typename T> struct If_ { typedef T enable; };
template<typename T> struct If_<false, T> { };

template<bool B, typename T> using If = typename If_<B, T>::enable;

template<size_t D> If<D!=0, double> my_func(...){}
template<size_t D> If<D==0, double> my_func(...){}

「Concepts Lite」の提案では、次のように 2 番目のオーバーロードを制約することで、はるかにクリーンな方法でこれが可能になると思います。

template<size_t D> double my_func(...){}

template<size_t D> requires (D == 0)
  double my_func(...){}

D==0ここで、2 番目のオーバーロードは、最初のオーバーロードよりも制約が厳しいため、次の場合にのみ呼び出すことができ、オーバーロードの解決によって選択されます。

于 2013-05-12T17:41:56.073 に答える