可变模板数据结构

Variadic template data structures

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

代码:

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

观察:提出这个问题的原因是为了了解可变模板操作,因此我不关心程序的使用,在上面的这个例子中:测试class正在失去访问权限生成的子 classes (rest ... )

问题:

  1. 第一个疑问: 我明白函数和classes可以有模板,但是 表示在定义“class 测试”之后?,我已经看到模板 < class T > class 一些 {},但从来没有看到模板 < classT>class一些{},下面看我对案例的理解:
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. 疑惑第三题:本题提到了第1题(<>是在结构体后定义的)的模板是 。 Test 在定义“struct Helper”之后是什么意思? 注意它的用法如下:“Test ”,而不是第一个 (1st) 主题中的“

  3. 疑惑第四题:本题提到了第二题(Print2推导模板的地方)为什么需要只传递 Test 作为类型,而不是 ?我想知道的是这个自推(“type”变成-> [T=int, Rest=])是怎么被C++搞出来的?注意第二个话题,其中对函数 Print2 的调用等同于 Print2 。使用 type = Test

第 4 个主题的补充:Helper::Print(ex),"type" 等效于 Test,我注意到“T " 变成了 "int"(第一种类型),"Rest" 变成了 ""(用于构建变量 "ex" 中的 sutrct Test 的其他类型)

提前致谢。

我将此答案献给提供 link 和研究技术名称的@super。谢谢!

1 和 3. 假设主模板是:

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

这意味着可以扣除其他(部分专业化),并且可以定义Struct / Class中的不同方法和值,示例:

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

print waits作为参数(T data,Rest ... others),即:"data"是T类型。那么Tdata就会是"ex"

如果我们把print func改成Print(Test & data),C++就会明白要传递的模板必须是结构体或者class满足条件为真,例如:Print < int, float, bool > (ex).

""是c/c++自动获取变量"ex"

见下例:

...
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 z​​a),必须和“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 < class T > struct Helper {}

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


模板 struct Helper <测试 >

意思是:传递给Helper的模板必须是满足表达式的struct / class类型,所以:

Helper > 满足条件,但是

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