1

我正在尝试制作一个函数模板,它将接受下面列出的两个(或更多)嵌套可变参数类模板作为参数,并将它们放入另一个将接受不同类型的数据结构中(我将最有可能使用)。以下是类和子类,以及我的函数的用法(该函数在下面进一步定义):

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);
}

我很好地掌握了参数包是如何被推导/推断的,以及auto,decltype和尾随返回类型是如何做的,但如果我弄错了,请告诉我如何做。

另外,如果有人愿意演示这个函数的可变参数版本,它可以接受任意数量的嵌套可变参数类模板并将它们放入合适的容器或数据结构中,那很好,但我主要关心的是完全理解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);
  }

};

您还可以在其中声明一些成员 typedefInnerEntity来指定外部类的类型,并据此制定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如果你不需要访问这些ArgsAInner类型,你就不需要那个东西,就像上面一样my_func。在这种情况下,你最好接受typename AInner并且少写。SFINAE 仍将确保只接受正确的内容。

于 2010-09-22T19:52:14.313 回答