42

他の任意のテンプレートをパラメーターとして取り、テンプレート名と適切に一致させることができるテンプレート関数を作成できるかどうか疑問に思っていました (つまり、結果のクラスだけではありません)。私が働くことを知っているのはこれです:

template<template<typename ...> class TemplateT, typename... TemplateP>
void f(const TemplateT<TemplateP...>& param);

たとえば、f(std::vector<int>())orには一致しますf(std::list<int>())が、 には機能しませんf(std::array<int, 3>())。2 番目のパラメーターは asize_tで型がないためです。

今、私は次のようなクレイジーなことをすることができると思います:

template<template<typename ...> class TemplateT, size... Sizes, typename... TemplateP>
void f(const TemplateT<Sizes..., TemplateP...>& param);

コンパイラがTemplateP省略記号またはSizes省略記号のいずれかが空になるように適切に導出することを期待しています。しかし、醜いだけでなく、型またはsize_tパラメーターのいずれかを取るテンプレートでも機能します。boolたとえば、パラメーターを含む任意のテンプレートとはまだ一致しません。

オーバーロードを使用したアプローチについても同じことが言えます。

template<template<typename ...> class TemplateT, typename... TemplateP>
void f(const TemplateT<TemplateP...>& param);

template<template<typename ...> class TemplateT, size... Sizes>
void f(const TemplateT<Sizes...>& param);

size_tさらに、とを混在させたい場合、このようなアプローチは機能しませんtypenames。したがって、何かに一致するために必要なものは次のようなものです。省略記号で許可されるものにまったく制約はありません。

template<template<...> class TemplateT, ... Anything>
void f(const TemplateT<Anything...>& param);

その構文は機能しませんが、このようなものを定義する他の構文があるのでしょうか?

これは主に、最初のパラメーターが常に固定されているさまざまなテンプレートがあり、戻り値の型に基づいて変更し、他のすべてを保持したい場合、言語で何が可能か疑問に思っています。実際に使用できる可能性があると思いました. このようなもの:

template<
    template<typename ValueT, ...> class TemplateT,
    ... Anything,
    typename ValueT,
    typename ResultT = decltype(some_operation_on_value_t(std::declval<ValueT>())>
TemplateT<ResultT, Anything...> f(const TemplateT<ValueT, Anything...>& in);

では、パターン マッチングを使用して、これを完全に一般的な方法で機能させる方法はありますか?

これは純粋な思考実験ではありません。なぜなら、私が立ち往生したユースケースは、コンテナーで動作し、不変の結果コンテナーを暗黙的に構築する純粋な機能プリミティブを作成することだったからです。結果コンテナーのデータ型が異なる場合、コンテナーが操作する型を知る必要があるため、コンテナーの唯一の要件は、テンプレートの最初のパラメーターが入力型である必要があるため、別の型に置き換えることができることです。結果の出力型ですが、コードはその後に続くテンプレート引数を無視する必要があり、それが型か値かを気にする必要はありません。

4

3 に答える 3

3

興味深いコンストラクトには、可変個引数テンプレートを使用した 2 つのレベルがあります。

  • 関数テンプレートの外側の可変個引数テンプレート パラメーター リストTemplateP&Sizes
  • テンプレート template parameter TemplateTクラス テンプレートのテンプレート パラメーターとしての内部パラメーター パック

まず、内部TemplateTクラスを見てみましょう: 省略記号演算子が のようなものと一致しないのはなぜTemplateT< int, 2 >ですか? 標準では、§14.5.3 で可変個引数テンプレートを次のように定義しています。

template<class ... Types> struct Tuple { };
template<T ...Values> struct Tuple2 { };

ここで、最初のケースのテンプレート引数 pack は型のみに一致し、2 番目のバージョンでは type の値のみTに一致する可能性があります。特に、

Tuple < 0 >    error;  // error, 0 is not a type!
Tuple < T, 0 > error2; // T is a type, but zero is not!
Tuple2< T >    error3; // error, T is not a value
Tuple2< T, 0 > error4; // error, T is not a value

すべて不正です。さらに、次のようなものにフォールバックすることはできません

template<class ... Types, size_t ...Sizes> struct Tuple { };

§14.1.11 で標準が述べているため:

プライマリ クラス テンプレートまたはエイリアス テンプレートのテンプレート パラメーターがテンプレート パラメーター パックである場合、それは最後のテンプレート パラメーターでなければなりません。関数テンプレートのテンプレート パラメーター パックは、そのテンプレート パラメーターが関数テンプレートのパラメーター タイプ リストから推定できる場合、または既定の引数 (14.8.2) を持っている場合を除き、別のテンプレート パラメーターを続けてはなりません。

つまり、クラス テンプレートの場合、1 つの可変引数パックのみが定義に表示されます。したがって、上記の (double)-variadic クラス定義は形式が正しくありません。内部クラスは常にそのような組み合わせを必要とするため、想像したほど一般的なものを書くことは不可能です。


救えるものは?外部関数テンプレートの場合、いくつかのシャードをまとめることができますが、気に入らないでしょう。2 番目のパラメーター パックが最初のパラメーター パックから推測できる限り、2 つのパラメーター パックが (関数テンプレートに) 表示される場合があります。したがって、次のような関数

template < typename... Args, size_t... N > void g(const std::array< Args, N > &...arr);
g(std::array< double, 3 >(), std::array< int, 5>());

整数値を推測できるため、許可されます。もちろん、これはコンテナの種類ごとに特化する必要があり、想像していたものとはかけ離れています。

于 2015-04-28T09:31:10.913 に答える
0

is_same_templateそよ風で特性を書くことができるようになるので、私たちがそのようなものを持っていれば素晴らしいでしょう.
それまでは、私たちはすべての方法を専門としています。

于 2016-12-02T12:27:07.987 に答える