C++17特性:扩展using声明

Using声明被扩展了,可以用来声明逗号分隔一组声明的列表。例如,现在可以这样写代码:

class Base {
  public:
    void a();
    void b();
    void c();
};
   
class Derived :private Base {
  public:
    using Base::a, Base::b, Base::c;
};

C++17之前,需要用三次using声明。

使用可变的using声明

逗号分隔的using声明提供了一种能力,可以泛化地从一组可变数量的基类中派生出相同类型的操作。这项技术特别酷的一个应用是创建一组lambda表达式的重载。定义如下:

tmpl/overload.hpp

// ”继承”所有传入的基类的operator():
template<typename... Ts>
struct overload : Ts...
{
    using Ts::operator()...;
};

// 基类型从传入的参数自动推导:
template<typename... Ts>
overload(Ts...) -> overload<Ts...>;

可以如下重载两个lambda表达式:

auto twice = overload {
     [](std::string& s) { s += s; },
     [](auto& v) { v *= 2; }
     };

这里我们创建了一个类型overload的对象,当我们使用推导指南去推导作为基模板类型overload的lambda表达式的类型,使用聚合初始化去初始化拥有闭包类型的拷贝构造函数的基类的子对象,每个lambda都是如此。然后using声明为每个类型overload生成operator()。如果没有using声明,基类就会为同一个operator()生成两个不同的重载,这就具有歧义了。结果是,可以传一个string,调用第一个重载函数,或传另一个类型,(只要提供了operator*=可用)调用第二个重载函数:

int i = 42;
twice(i);
std::cout << "i: " << i << '\n';
std::string s = "hi";
twice(s);
std::cout << "s: " << s << '\n';
// 打印: 84
// 打印: hihi

这项技术的一种应用是std::variant visitors。

继承构造函数的可变using声明

与继承构造函数声明一样,现在还允许这样:可以声明一个可变类模板Multi,从每个它传来的基类派生:

tmpl/using2.hpp

template<typename T>
class Base {
    T value{};
public:
    Base() {
        ...
    }
    Base(T v) : value{v} {
        ...
    }
    ...
};

template<typename... Types>
class Multi :private Base<Types>...
{
public:
    // derive all constructors:
    using Base<Types>::Base...;
    ...
};

针对所有基类构造函数的using声明,可以为每个类型对应的构造函数派生。现在,当为3个不同类型声明Multi<>类型:

using MultiISB = Multi<int,std::string,bool>;

可以使用每个对应的构造函数声明对象:

MultiISB m1 = 42;
MultiISB m2 = std::string("hello");
MultiISB m3 = true;

通过新的语言规则,每个初始化调用了匹配到的基类对应的构造函数或者所有其他基类的缺省构造函数。因此

MultiISB m2 = std::string("hello");

Base<int>调用了缺省构造函数,string的构造函数用于Base<std::string>,为Base<bool>使用缺省构造函数。原理上讲,还可以在Multi<>使能所有赋值操作符:

template<typename... Types>
class Multi :private Base<Types>...
{
    ...
    // 派生所有operator=:
    using Base<Types>::operator=...;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值