C++17那些事开篇之类模版参数推导(CTAD)

C++17那些事开篇之类模版参数推导(CTAD)

引入

大家好,我是光城,今天开始正式开篇C++17的新特性了,期待不,欢迎留言区说出想要更新的特性呀~

C++模板元编程一直是C++开发者们熟知的一项功能,无论是初学者还是高级开发者都能够通过它编写具有类型参数的通用代码。随着C++17引入的类模板参数推导(CTAD),处理类模板的过程变得更加直观和灵活。

本节所有代码也会更新于社群中。

C++17引入CTAD会带来如下好处:

例如:这么复杂的代码

std::vector<FooBar<int, const char*>> obj{a, b, c};

我们只需要:

std::vector obj{a, b, c};

再比如:

std::tuple<int>

可以简化为:

std::tuple t1{1};

所以,咱们今天来看看CTAD。

CTAD全称是Class template argument deduction (CTAD),类模版参数推导,你给定编译器一个推导指南(deduction guide),我们便可以使用这个特性了。

如果不给定,如下面例子:

#include <iostream>
template <typename T, typename U>
struct MyPair {
  T first{};
  U second{};
};

int main() {
  MyPair<int, int> p1{1, 2};
  MyPair p2{1, 2};
  std::cout << p1.first << ", " << p1.second << std::endl;
  std::cout << p2.first << ", " << p2.second << std::endl;
  return 0;
}

对于p2,我们便会报错:

no viable constructor or deduction guide for deduction of template arguments of 'MyPair'

那么对于怎么修改呢?

只需要添加deduction guid即可,如下写法即可。

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

类模板参数推导(CTAD)通过允许编译器从构造函数参数中推导出模板参数,简化了类模板的实例化过程。在引入CTAD之前,开发者在实例化时必须明确指定模板参数。然而,通过CTAD,这种明确的指定变得不再必要,从而使代码更易读、易维护。

template <typename T>
class Add{
    private:
        T first;
        T second;
    public:
        Add() = default;
        Add(T first, T second): first_{first}, second_{second} {}
        T result() const { return first + second; }
};

int main(){
    Add one(1,2);               // T被推导为int
    Add two{1.245, 3.1415};     // T被推导为double
    Add three = {0.24f, 0.34f}; // T被推导为float
}

在上面的示例中,CTAD允许类型T基于构造函数参数被推导,消除了显式类型指定的需求。

非静态成员初始化

但是有个场景用不了CTAD,那就是非静态成员初始化。例如:Test类中使用外面的MyPair就必须写全。

template <typename T = int, typename U = int>
struct MyPair {
  T first{};
  U second{};
};

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

class Test {
  MyPair p4;   // use of class template 'MyPair' requires template arguments; argument
               // deduction not allowed in non-static class member
};

在上面的例子中,我们定义了一个模板类MyPair,并在其中使用了CTAD。然而,当我们尝试在类Test中使用MyPair作为非静态成员时,由于非静态成员初始化的上下文,CTAD将无法正常工作,导致编译错误。在这种情况下,我们必须显式指定MyPair的模板参数。

我们可以看到在非静态成员初始化的上下文中,CTAD无法推导模板参数。因此,在类模板作为非静态成员时,开发者需要显式指定所有的模板参数。这一点需要在实际开发中特别注意,以确保代码的正确性和可维护性。

欢迎与我一起交流学习C++那些事,相关源码与资料已更新社群。

515cec7efb83bf7f35efd0bb35023d0e.jpeg

9bfc32441b6810e1e673bd28c41d5b62.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值