2017-07-04 11 views
4

template styleに固有のコンパイル時のダックタイピングを使用する場合、テンプレート引数が特定のシグネチャを持つ特定のメソッドを実装するという要件を強制する方法はありますか?もちろんC++テンプレートで正式なプロトコルを実行するにはどうすればよいですか?

struct ProtocolT { 
    void g() const; 
    void h(); 
} 

// I want the compiler to check that T conforms to ProtocolT 
// that is, T must implement g() and h() rather than just g() 
template <typename T> 
void f(const T& x) { 
    x.g(); 
} 

、これさえなくて、完璧な型の安全性があります:テンプレート引数Tは、テンプレート関数の実装で使用される方法を持っていない場合、コンパイラは常に文句を言うでしょう。

しかし、class Tには、class ProtocolTに指定されているすべてのメソッドが必要であることが明確に示されています。私がまだテンプレート関数の実装で使用していないメソッドをTから要求することで、開発プロセスの初期段階で設計を制約することができます。

ProtocolTに未使用のメソッドが含まれていなくても、Tとして使用可能なクラスを作成する必要があるときには、検証済みのプロトコル準拠が役立つと思います。 (もちろん、誰も文書化のためProtocolTを書いてから私を停止していないが、その後、コンパイラはProtocolTが少なくとも必要なすべてのメソッドが含まれていることを検証しません。)

+0

継承を「T」を出す。 –

+0

[static-polymorphism-make-sense-for-implement-an-interface]に関連する(https://stackoverflow.com/questions/20771210/does-static-polymorphism-make-sense-for-implementing-an) -interface) – Jarod42

答えて

4

あなたが探している機能は、conceptsとして知られています。これらは現在、技術仕様です。 GCCにはliteのコンセプトが実装されています。あなたが使用できるソリューションが必要な場合は、しかし、

template <typename T> 
concept bool Protocol = requires(const T a, T b) { 
    { a.g() } -> void; 
    { b.h() } -> void; 
}; 

void f(const Protocol& x) { 
    x.g(); 
} 

:概念を使用して

は(私は構文を使用して、あまりにも慣れていないよ、それはおそらく若干異なるだろう)のようになります。 今すぐを使用すると、さまざまな手法でコンセプトをエミュレートできます。

機能が目的の機能を果たしているかどうかを検出するための型特性を書くことができます。

また、以前の手法を抽象化して定型文を大幅に削減するdetection idiomを使用することもできます。あなたの例:それを使用して

template <typename T> 
using g_t = decltype(std::declval<const T&>().g()); 

template <typename T> 
using h_t = decltype(std::declval<T&>().h()); 

template <typename T> 
constexpr bool meets_protocol_v = std::experimental::is_detected_exact_v<void, g_t, T> 
      && std::experimental::is_detected_exact_v<void, h_t, T>; 

、あなたはmeets_protocol_vのオフSFINAEフレンドリーでSFINAE可能性のいずれか、またはあなたがアサート静的ことができます:実装し、その後SFINAEを強制するProtocolT` `から

template <typename T> 
void f(const T& x) { 
    static_assert(meets_protocol_v<T>, "Doesn't meet protocol"); 
    x.g(); 
} 
2

たぶんstatic_assert対応する挿入:

static_assert 
(
    ::std::is_same< void, decltype(::std::declval<T>().h()) >::value 
, "T must implement void h(void)" 
); 

また、あなたの例では、TがProtocolTの要件に従うときには、fconstのTへの参照を受け入れるので、まだ動作しません。ProtocolTにはnon-const g()が必要です。

+0

'const':thx、fixed! – max

関連する問題