1. 介绍及例子

简称叫CTAD: class template argument dedution,类模板参数推导。

就是在使用模板类的时候,你可以不用显式的指定参数的类型了。

而是由编译器自动进行推导。

比如说:

#include <utility>
#include <iostream>
#include <vector>

int main()
{
    std::vector arr = { 1,2,3 };

    for (auto &v: arr) {
        std::cout << v << " ";
    }
    std::cout << "\n";

    std::pair p = {1.1f,-2.0f};

    std::cout << p.first << " " << p.second << std::endl;
    return 0;
}

2. 类模板推断指引

但是C++坑就坑在它永远有填不完的坑,C++17的类模板参数

推导它不支持聚合类。

比如下面代码:

p2就无法推导出来!!!

#include <iostream>


template<typename T, typename U>
struct Pair {

    T t{};
    U u{};
};
int main()
{

    Pair<int,int> p1{10,10};

    Pair p2{20,20};


    return 0;
}

编译器会提示没有匹配的类型。


ctad_agg_guide.cc: In function ‘int main():
ctad_agg_guide.cc:19:18: error: class template argument deduction failed:
   19 |     Pair p2{20,20};
      |                  ^
ctad_agg_guide.cc:19:18: error: no matching function for call to ‘Pair(int, int)

这时我们需要手动给这个模样写推导的指引:

template <typename T, typename U>
Pair(T, U) -> Pair< T, U >;

加上之后就可以推导了。

不过这个坑在C++20好像就填了。

顺带一提这个类型模板是可以带默认的参数的。

template<typename T = int, typename U = int>
struct Pair {

    T t{};
    U u{};
};

int main() {
	
	Pair p; // default Pair<int, int>
	return 0;	
}

3. 非静态成员初始化

对于类里面的非静态成员初始化,是无法使用类模板推导的。

需要手动指定参数的类型!!!


#include <utility> // for std::pair

struct Foo
{
    std::pair<int, int> p1{ 1, 2 }; // ok, template arguments explicitly specified
    std::pair p2{ 1, 2 };           // compile error, CTAD can't be used in this context
};

int main()
{
    std::pair p3{ 1, 2 };           // ok, CTAD can be used here
    return 0;
}

这里p2会报错

ctad_nonstatic_init.cc:6:5: error: invalid use of template-name ‘std::pair’ without an argument list
    6 |     std::pair p2{2,3};

4. 参考

learncpp-ctad

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐