前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++17常用新特性(九)---扩展的using声明

C++17常用新特性(九)---扩展的using声明

作者头像
CPP开发前沿
发布2022-04-13 15:34:22
9260
发布2022-04-13 15:34:22
举报
文章被收录于专栏:CPP开发前沿

从C++17开始,using声明语句被扩展了,声明多个标识符时可以在一行进行声明,用逗号分隔即可。如下面的代码所示:

代码语言:javascript
复制
namespace A
{
    void g(){cout<<"g()"<<endl;};
    void f(){cout<<"f()"<<endl;};
}
namespace X
{
    using A::f, A::g;
}

在C++17之前,使用多个using声明时要分别进行声明。

1 使用变长的 using 声明

在实际编程时,通过使用可变的 using 声明可以实现泛型代码从可变数量的所有基类中派生同一种运算。这种方法的典型应用场景就是可以创建一个统一的lambda操作符重载。如下面的代码,通过可变类模板和一个自动推断向导实现了一个实现重载统一定义的lambda表达式。

代码语言:javascript
复制
#include <iostream>
using namespace std;
template<typename... Ts>
struct overload : Ts...
{
  using Ts::operator()...;
};

template<typename... Ts>
overload(Ts...) -> overload<Ts...>;

auto operCalc = overload {
    [](std::string& s) { cout<<s<<endl;; },
    [](auto& v) { v *= 2; }
    };

int main()
{
   
    string str = "hello";
    operCalc(str);
    auto sum=1.5;
    operCalc(sum);
    cout<<sum<<endl;
    return 0;
}

在支持C++17的编译器中,上面的代码可以正常运行结果,针对上面的代码解释如下:

代码语言:javascript
复制
template<typename... Ts>
struct overload : Ts...
{
  using Ts::operator()...;
};

上面这个实际是定义一个可变的类模板,template<typename... Ts>是类模板的可变参数包。struct overload : Ts...这里Ts实际上是overload基类继承的所有参数类型。using Ts::operator()...就是一个可变的using声明。

overload(Ts...) -> overload<Ts...>实际上是一个自动推导器,用来告诉编译器根据传入的参数类型推导出类模板的参数类型。

在上面的示例中,如果传入的是string类型参数,会匹配到[](std::string& s) { cout<<s<<endl;; },如果传入整型或者auto的数值型参数则会匹配到[](auto& v) { v *= 2; }这个lambda表达式。

除了这个应用场景外,这个技术的另一个典型应用是std::variant 访问器。这个访问器将在后续的文章中进行介绍。

2 使用变长 using 声明继承构造函数 在C++17中,可以声明一个可变参数的类模板。这个类模板可以继承一个基类。基类可以代表任意参数类型。如下面的代码:

代码语言:javascript
复制
template<typename T>
class Base
{
public:
  Base(){};
  Base(T _v):value(_v){cout<<value<<endl;};
private:
    T value{};
};

template<typename... Types>
class SubClass:private Base<Types> ...
{
public:
    using Base<Types>::Base...;
};

int main()
{
   
    using SubClassInst = SubClass<int,double,std::string,bool>;
    SubClassInst strTmp(std::string("hello,world"));
    SubClassInst iTmp(100);
    SubClassInst dTmp(50.4);
    return 0;
}

在上面代码中,派生类中使用了基类构造函数的using声明,就是派生类具备继承了每一种传入类型的声明。如在本例中,使用using声明了4种类型。

代码语言:javascript
复制
using SubClassInst = SubClass<int,double,std::string,bool>;

声明后就可以使用SubClassInst定义已经声明了的数据类型变量。上面的代码运行结果为:

3 总结

如果想要深入了解using声明请参考下面两个链接:

参考链接: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0195r0.html http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0195r2.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CPP开发前沿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档