微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

可变模板数据结构

如何解决可变模板数据结构

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

代码

    #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,bool>
      
        Print1(ex);
    
        Print2(ex);
    
        Helper<type>::Print(ex);
      
        std::cout << "END!" << std::endl;
        return 0;
    }

观察:问这个问题的原因是为了理解varidiac模板操作,为此我不关心程序的使用,在上面的这个例子中:Test class is lost access to the generated sub-classes (休息……)

问题:

  1. 疑问的第一个话题: 我知道函数和类可以有模板,但是在定义“类测试”之后 是什么意思?,我已经看过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 ”,而不是第一个(第一个主题中的“

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

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

提前致谢。

解决方法

我将此答案献给@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,bool> -> value = 3
Test <int,std::string> -> value = 3
Test <int,floot,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,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,bool> ex(15,41.59,true);

  Print(ex);
  return 0;
}

打印等待作为参数(T数据,Rest ...其他),即:“数据”是T类型。那么T 数据将是“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,true);

  Print(ex,50);
  return 0;
}

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

A 是“int”

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 C>
struct Helper<Test<A,C>> {
   int value = 3;

   void PrintA(A value){}

   void PrintB(B value){}

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

任何用单个 参数初始化的“Helper”结构将具有 value = 2

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

示例:

Helper<int> -> value = 2

Helper<Test<int,float>> -> value = 3
Helper<Test<int,char>> -> value = 3
Helper<Test<char,double>> -> value = 3

Anything other than: "<int>" and "<Test<A,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的模板必须是满足表达式的struct/class类型,所以:

Helper > 满足条件,但是

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。