【问题标题】:Variadic template data structures可变模板数据结构
【发布时间】:2021-07-01 03:15:06
【问题描述】:

可变参数模板是接收不同数量参数的模板,可以与可操作泛型类型的模型一起使用

代码:

    #include <iostream>
    
    template <class ...Rest>
    struct Test {};
    
    template <class T, class ...Rest>
    struct Test <T, Rest...> {
        Test(T first, Rest... rest)
          : first(first)
         {}
    
        T first;
    };
    
    template <class T>
    void Print1(T &data)
    {
        std::cout << data.first << std::endl;
    }
    
    template <class T, class ...Rest>
    void Print2(Test<T, Rest...> &data)
    {
        std::cout << data.first << std::endl;
    }
    
    template <class T>
    struct Helper;
    
    template <class T, class ...Rest>
    struct Helper<Test<T, Rest...>> {
       static void Print(Test<T, Rest...> &data){
           std::cout << data.first << std::endl;
       }
    };
    
    int main() {
        Test<int, float, bool> ex(15, 41.59, true);
    
        using type = decltype(ex); //Test<int, float, bool>
      
        Print1(ex);
    
        Print2(ex);
    
        Helper<type>::Print(ex);
      
        std::cout << "END!" << std::endl;
        return 0;
    }

观察:问这个问题的原因是为了了解varidiac模板操作,为此我不关心程序的使用,在上面这个例子中:Test类正在失去对生成的子类的访问权限(休息……)

问题:

  1. 疑问的第一个话题: 我知道函数和类可以有模板,但是在定义“class Test”之后的是什么意思? ,我已经看过template class Some {},但是没见过template class Some {},看下面我对案例的理解:
template <class T, class ...Rest>
void Func(T first, Rest ...rest){
    std::cout << first << std::endl;

    Func(rest...); //1 call is [T=float,Rest=<bool>], and 2 call is [T=bool] (Futures calls)
}
//Call: Func (1, 1.55, true), [T equals "int", Rest equals <float, bool>]
  1. 疑问之二: 在函数“Print2”中,为什么推导出Print2调用的模板是参数是变量“ex”,我不明白为什么结果不同于:[T = Test ] (Print2>)。相反,得到的结果是 [T = int, Rest = ] (Print2)

  2. 疑问的第三个话题:这个话题提到了第一个话题(是在结构之后定义的)模板是 . Test 在定义“struct Helper”之后是什么意思?注意它的用法如下:“Test ” , 而不是第一个 (1st) 主题中的“

  3. 疑问的第四个话题:这个话题提到了第二个话题(模板是为Print2推导出来的)为什么只需要通过测试为类型,而不是 ?我想知道的是这个自我演绎(“type”变成-> [T=int, Rest=])是怎么用C++做出来的?请注意,在第二个主题中,对函数 Print2 的调用等效于 Print2 。使用 type = Test

第四题的补充:Helper::Print(ex), "type" is equivalent to Test,我注意到"T"变成了"int" (第一种类型),“Rest”变为“”(用于构建变量“ex”中的 sutrct 测​​试的其他类型)

提前致谢。

【问题讨论】:

  • 看看How to Ask。每个问题只有 1 个问题。另外,在询问之前尝试自己做一些研究。你在看partial specializations
  • @super 谢谢,我不知道用哪个名字来研究,“部分专业化”以及链接帮助很大。我会考虑到这一点进行研究。

标签: c++ templates variadic-templates variadic-functions variadic


【解决方案1】:

我将此答案献给@super,它提供了研究的链接和技术名称。谢谢!

1 和 3。 假设主模板是:

template <size_t ...Rest>
struct Test {
   int value = 1;
};

这意味着可以扣除其他(部分特化),并且可以在结构/类中定义不同的方法和值,例如:

template <size_t A>
struct Test <A, A*2> {
  int value = 2;
}

任何用 2 个参数初始化的“测试”结构,第二个是第一个 (A*2) 的双精度值 = 2。示例:

Test<5, 10> -> value = 2
Test <3, 6> -> value = 2;

Anything other than: "<A, A * 2>" will be assigned to the primary template

Test <1, 2, 3, 4> -> value = 1;
Test <4, 5> -> value = 1;
Test <3, 6, 8> -> value = 1;

也就是说,回复第一个话题:

template <class ...Rest>
struct Test {
  int value = 1;
};

template <class T, ...Rest>
struct Test <T, Rest...> {
  int value = 2;
};

辅助模板的条件必须满足主模板,在本例中为:“template struct Test {}”,然后任意辅助模板:template struct Test 将永远为真,因为 Rest ... 表示 0 或更多,而“T”是第一个参数

下面的例子:

Test<int, bool> -> value = 2
Test <bool, float> -> value = 2
Test <bool> -> value = 2
Test <std::string> -> value = 2

但您也可以创建其他辅助模板:

template <class ...Rest>
struct Test {
  int value = 1;
};

template <>
struct Test <int, float> {
  int value = 2;
};

template <class ...Rest>
struct Test <int, float, bool, Rest...> {
  int value = 3;
};

在上面的这个例子中,你说的是:

如果类型为“”,则值为 2 [确切的两个参数,int 和 float]

如果类型是 则值为 3 [前三个参数是 int 和 float 和 bool,其余的如果有的话]

例子:

Test <int, float> -> value = 2

Test <int, float, bool> -> value = 3
Test <int, float, bool, std::string> -> value = 3
Test <int, floot, bool, std::string, char> -> value = 3

Any other that does not satisfy any of the secondary templates will be assigned to the primary

Test <bool, float> -> value = 1
Test <int> -> value = 1
Test <int, float, char> -> value = 1

2. 让我们假设以下代码

...
template <class T, class ...Rest>
void Print(T data, Rest ...others){
   std::cout << data.first << std::endl;
}

int main(){
  Test<int, float, bool> ex(15, 41.59, true);

  Print(ex);
  return 0;
}

打印等待作为参数(T data, Rest ... others),即:“data”的类型是T。那么T data将是“ex”

如果我们把print func改成Print(Test & data),C++就会明白,要传递的模板必须是满足条件为真的结构或类,示例:打印 (ex).

”由变量“ex”的c/c++自动获取

请看下面的例子:

...
template <class A, class B, class C>
void Print(Test<A, B, C> &data, A za, B zq){
    std::cout << data.first << std::endl;
    std::cout << za << std::endl; //float
    std::cout << zq << std::endl; //bool
}

int main(){
  Test<int, float, bool> ex(15, 41.59, true);

  Print(ex, 50);
  return 0;
}

再一次“”是在Print(ex)时由变量“ex”的c/c++自动得到的

A 是“整数”

B 是“浮动”

C 是“布尔”

函数“Print”的第二个参数(A za),必须与“A”(int)扣除的参数类型(int)相同,第三个参数(B zq)相同

3.让我们假设以下代码:

template <class T>
struct Helper {
  int value = 1;
};

template <>
struct Helper <int> {
  int value = 2;
};

template <class A, class B, class C>
struct Helper<Test<A, B, C>> {
   int value = 3;

   void PrintA(A value){}

   void PrintB(B value){}

   void PrintAll(A aval, B bval, C cval){}
};

使用单个 参数初始化的任何“Helper”结构的值 = 2

使用不同于 和 Test 的单个参数初始化的任何“Helper”结构的值 = 1;

例子:

Helper<int> -> value = 2

Helper<Test<int,bool,float>> -> value = 3
Helper<Test<int,float,char>> -> value = 3
Helper<Test<char,std::string,double>> -> value = 3

Anything other than: "<int>" and "<Test<A,B,C>>" will be assigned to the primary template

Helper <bool> -> value = 1
Helper <float> -> value = 1
Helper <char> -> value = 1

注意,二级模板必须满足一级模板,即:template struct Helper {}

因此,“Helper”定义后的二级模板必须只包含单个“T”,例如,或,或>


模板 struct Helper >

这意味着:要传递给Helper的模板必须是满足表达式的结构/类类型,所以:

Helper > 满足条件,但是

Helper>不满足,因为int扣除了“A”,float扣除了“B”,而“C”为空

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 2019-08-04
    • 1970-01-01
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    相关资源
    最近更新 更多