简体   繁体   English

接受嵌套的可变参数类模板作为函数模板的参数

[英]Accepting nested variadic class templates as arguments to function template

I'm trying to make a function template that will accept two (or more) of the nested variadic class templates listed below, as arguments, and put them into another data structure that will accept different types (pair or tuple is what I'll most likely use). 我正在尝试创建一个函数模板,它将接受下面列出的两个(或更多)嵌套的可变参数类模板作为参数,并将它们放入另一个将接受不同类型的数据结构中(对或元组就是我要做的)最有可能使用)。 Here are the classes and subclasses, along with the usage of my function (the function is defined farther below): 以下是类和子类,以及我的函数的用法(该函数在下面进一步定义):

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

Below is the code I cobbled together for the function, and it does compile fine, but I'm not sure if it is set up correctly. 下面是我拼凑的函数代码,它编译得很好,但我不确定它是否设置正确。 Specifically, I'm a little fuzzy on how typename and ::template are making the compiler happy in this context, or if this function will behave the way I'm expecting: 具体来说,我对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);
}

I think I have a good grasp on how the parameter packs are being deduced/inferred, and how auto , decltype , and the trailing return type are doing their thing, but if I'm mistaken, please let me know how. 我已经很好地掌握了如何推导/推断参数包,以及autodecltype和尾随返回类型如何做他们的事情,但如果我弄错了,请让我知道如何。

Also, if anyone cares to demonstrate a variadic version of this function that can accept any number of the nested variadic class templates and put them into a suitable container or data structure, that'd be great, but I'm primarily concerned with fully understanding typename and ::template . 此外,如果有人想要证明这个函数的可变版本可以接受任意数量的嵌套可变参数类模板并将它们放入合适的容器或数据结构中,那就太好了,但我主要关心的是完全理解typename::template Thanks ahead of time! 提前谢谢!

*If I've worded this title incorrectly or I'm mixing up terms, please explain. *如果我错误地说了这个标题,或者我正在混淆条款,请解释一下。 :) I'm here to learn. :)我在这里学习。

This will not work because Entity<Args>::InnerEntity is a non-deduced context. 这不起作用,因为Entity<Args>::InnerEntity是一个非推断的上下文。 Means that ArgsA... and ArgsAInner... cannot be deduced, likewise for the other parameter. 意味着ArgsA...ArgsAInner...无法推断,同样对于其他参数。 This is because before the compiler can deduce Args , it has to know what type InnerEntity is a member of, but to know that , it has to deduce Args . 这是因为之前的编译器可以推断出Args ,它必须知道什么类型的InnerEntity是的一员,但是要知道 ,它必须根据Args

You can put this function as a friend function template into Entity<Args...> and make it work as long as both are members of the same template. 您可以将此函数作为友元函数模板放入Entity<Args...> ,只要两者都是同一模板的成员,就可以使其工作。 But last time I checked, GCC did not find friend functions defined in class templates. 但是上次我检查时,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);
  }

};

You could also declare some member typedef in InnerEntity that specifies the type of the outer class, and formulate my_func in terms of that, so that SFINAE can sort it out for non-members. 您还可以在InnerEntity中声明一些指定外部类类型的成员typedef, InnerEntity根据该类型制定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);
}

Of course you don't need that template<typename...> class AInner thing if you don't need to access the ArgsAInner types, like in the above my_func . 当然,如果你不需要访问ArgsAInner类型,就像上面的my_func一样,你不需要那个template<typename...> class AInner my_func In such a case you are better off just accepting typename AInner and have less to write. 在这种情况下,你最好只接受typename AInner并且写得更少。 The SFINAE will still make sure only the right thing is accepted. SFINAE仍将确保只接受正确的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM