2017-12-25 12 views
1

タイプテンプレートパラメータを特定のテンプレートのインスタンス化のみを受け入れるように制約する慣用方法とは何ですか?特定のテンプレートのインスタンス化のみを行うタイプのテンプレートパラメータを制限する

例えば、

template<typename P> 
class C { 
    C() = default; 
    ... 
}; 

template<typename T> 
class Accepted { 
    ... 
}; 

template<typename T> 
class Other { 
    ... 
}; 

C<Accepted<float>> obj1; // should compile 
C<Accepted<int>> obj2; // should compile 
C<Other<int>>  obj3; // should not compile 
C<double>   obj4; // should not compile 
+0

「C 」のようなものはどうですか? – StoryTeller

+0

@StoryTellerはコンパイルしないでください。追加するように編集しました。 – Danra

+0

部分的な解決策としては、 'テンプレートクラスC;'として宣言し、 'テンプレート<テンプレート型名TT、型名T>構造体C > {...}'と定義し、TTが受け入れられる静的アサーション、それはあなたが満足している契約のみを表明することでリラックスすることができます。私は、一般的には、Acceptedを設計して内部的にその契約が満たされていることを要求/宣言し、与えられたタイプのAcceptedのインスタンス化が適切に行われていると主張する以上の型にCを無視します。 –

答えて

3

専門は答えです。

template<typename P> class C; 

template<typename T> 
class Accepted { 
    ... 
}; 

template<typename P> 
class C<Accepted<P>> { 
    C() = default; 
    ... 
}; 

以上がインスタンス化するとき、それは専門を選択するための任意のC<Accepted<T>>がよく形成することができます。 C<T>のようなものは、一次特殊化を選択しますが、これは定義されていないため、コンパイルされません。

+0

私はこれが書かれているように、OPのニーズに合うように少し適応する必要があると思っています - これは代替が定義されるまでのみ動作します。詳細な情報はなく[X-Y問題](http://mywiki.wooledge.org/XyProblem)のように聞こえるが、正確な表現は「明示的なアサーションを必要とする特定のテンプレートのインスタンス化のみを受け入れる」というものだった。私は、[コンセプト](https://en.wikipedia.org/wiki/Concepts_(C%2B%2B))に近いものではない場合、 'std :: is_base_of'を提案しましたが、XYに対する私の一般的なアプローチは答えています質問の手紙と精神の両方で –

+0

@JohnP - それでは、是非お答えください。 SOの強みは答えの多様性です。 – StoryTeller

+0

私は最初のレスポンダーと競争するために議論に十分なものを持っているとは思っていません。私は大まかな草案に取り組んでいる間に包括的な解決策を提示することに慣れていますが、すべて。 –

2

私は文脈についてもっと知ることなく、2つの可能な答えを見ています。

template<typename T> class C; 
template<template<typename> typename TT, typename T> class C<TT<T>> { 
... static_assert(std::is_same<TT<T>, Accepted<T>>::value, "The given type is not an instantiation of Accepted!"); ... 
} 

これは非常に有用です - これは何のために特別ですか? 2番目のテンプレートがあるとします。 SortedAccepted<T>という同じ要件を満たしていますが、テンプレート引数をAccepted<T>に制限しています。

1つのオプションは、自分自身を受け入れたとして、それからの派生は同じ制約条件を満たさなければならないように契約として受け入れ設計することです:

template<template<typename> typename TT, typename T> class C { 
... static_assert(std::is_base_of<Accepted<T>, TT<T>>::value, 
    "The given type is not a derivation of Accepted!"); ... 
}; 

これが受け入れを延長する必要があることを設計原理から、次のではなく、その派生によって、修正された。前の例から、Acceptedは冪等のソートメソッド(accepted.sort().sort() == accepted.sort())を必要とするかもしれませんが、SortedAcceptedは暗黙的にこのプロパティを保持しますが、さらにsorted_accepted.sort() == sorted_acceptedを提供します。 Acceptedが期待される場所であればどこでもSortedAcceptedを許可することで失うものはありませんが、十分に得ることができます!

私があなたの問題を正しく理解していれば、あなたは形質とコンセプトに興味があるかもしれません。

<type_traits>およびBoost's extensionsに見られるタイプの形質は、形質を共有するコレクション、これらの表現などについてコンパイル時の保証を提供します。たとえば、S s; T t; auto u = s + tの場合、std::is_arithmetic<S>::valueおよびstd::is_arithmetic<T>::valueがtrueの場合、std::is_arithmetic<decltype(u)>::valueがtrueになります。 is_floating_pointのいずれかである場合、uも同様です。

Conceptsは、型形質由来の次の論理的ステップである:本質的にはreified要件の形質である。 ( 'Concepts Lite')

関連する問題