1

以下にリストされているネストされた可変個引数クラス テンプレートの 2 つ (またはそれ以上) を引数として受け入れ、それらを異なる型を受け入れる別のデータ構造に入れる関数テンプレートを作成しようとしています (ペアまたはタプルは私がするものです使用する可能性が高い)。クラスとサブクラス、および関数の使用法を次に示します (関数は後で定義します)。

template<typename... Args> struct Entity {

    template<typename... InnerEntArgs> struct InnerEntity {
        InnerEntity(InnerEntArgs... inner_ent_args) {
            ... //do stuff w/ InnerEntArgs pack
            ... //do stuff that makes Inner dependent on Outer's Args pack
        }
    };
};

struct ThingA : Entity<int, string> {
    ... //construct ThingA
};

struct ThingB : Entity<string, string> {
    ... //construct ThingB
};

auto foo = my_func(
    ThingA::InnerEntity<int, int, int>(1, 2, 3)
    , ThingB::InnerEntity<string, int>("bar", 1)
);

以下は、関数用にまとめたコードで、正常にコンパイルされますが、正しく設定されているかどうかはわかりません。typename具体的には、このコンテキストでコンパイラをどのように満足させて::templateいるか、またはこの関数が期待どおりに動作するかどうかについて、少しあいまいです。

template<
    typename... ArgsA, typename... ArgsAInner
    , typename... ArgsB, typename... ArgsBInner
> auto my_func(
    typename Entity<ArgsA...>::template InnerEntity<ArgsAInner...> A
    , typename Entity<ArgsB...>::template InnerEntity<ArgsBInner...> B
) -> tuple<decltype(A), decltype(B)> {
    return make_tuple(A, B);
}

パラメーター パックがどのように推定/推論されているか、および、 、および末尾の戻り値の型がどのように機能しているかについては十分に把握していると思いますが、間違っている場合はその方法を教えてください。autodecltype

また、ネストされた可変個引数クラスのテンプレートをいくつでも受け入れて適切なコンテナーまたはデータ構造に入れることができるこの関数の可変個引数バージョンを誰かが実証したい場合、それは素晴らしいことですが、私は主に完全に理解することに関心がありますtypename::template。お早めにどうぞ!

*このタイトルの表現が間違っていたり、用語を混同している場合は、説明してください. :) 私は学ぶためにここにいます。

4

1 に答える 1

4

Entity<Args>::InnerEntityは推論されていないコンテキストであるため、これは機能しません。ArgsA...およびArgsAInner...は、他のパラメーターと同様に推測できないことを意味します。これは、コンパイラが を推測する前に、Argsどの型InnerEntityがメンバーであるかを知る必要があるためですが、それを知るは、 を推測する必要がありArgsます。

この関数をフレンド関数テンプレートとして入れてEntity<Args...>、両方が同じテンプレートのメンバーである限り機能させることができます。しかし、前回チェックしたとき、GCC はクラス テンプレートで定義されたフレンド関数を見つけられませんでした。

template<typename ...Args>
class Entity {
  template<typename ...ArgsInner>
  class InnerEntity {

  };

  template<typename ...ArgsAInner, typename... ArgsBInner>
  > friend auto my_func(
        InnerEntity<ArgsAInner...> A
      , InnerEntity<ArgsBInner...> B
  ) -> tuple<decltype(A), decltype(B)> {
      return make_tuple(A, B);
  }

};

InnerEntityまた、外部クラスの型を指定するメンバー typedef を宣言しmy_func、それに関して定式化して、SFINAE が非メンバーに対してそれを分類できるようにすることもできます。

template<typename ...Args>
class Entity {
  template<typename ...ArgsInner>
  class InnerEntity {
    typedef Entity outer_entity;
  };    
};

template<typename A, typename B, typename Result>
struct require_entity { };

template<typename ...ArgsA, typename ...ArgsB, typename Result>
struct require_entity<Entity<ArgsA...>, Entity<ArgsB...>> {
   typedef Result type;
};

template<template<typename...> class AInner, template<typename...> class BInner, 
         typename ...ArgsAInner, typename ...ArgsBInner>
> auto my_func(
      AInner<ArgsAInner...> A
    , BInner<ArgsBInner...> B
) -> typename require_entity<
         typename AInner<ArgsAInner...>::outer_entity, 
         typename BInner<ArgsBInner...>::outer_entity, 
           tuple<decltype(A), decltype(B)>>::type 
{
    return make_tuple(A, B);
}

もちろん、上記のように型template<typename...> class AInnerにアクセスする必要がない場合は、その必要はありません。そのような場合は、ただ受け入れて、書くことを減らしたほうがよいでしょう。SFINAE は、正しいものだけが受け入れられるようにします。ArgsAInnermy_functypename AInner

于 2010-09-22T19:52:14.313 に答える