首页 > 编程语言 >c++-----declval

c++-----declval

时间:2024-05-13 14:41:10浏览次数:13  
标签:std 返回 decltype declval int c++ ----- 类型

std::declval

基本概念和常规实例

std::decval–C++新标准中出现的函数模板,没有函数体(只有声明、没有实现),无法调用,一般用于与decltype,sizeof等关键字配合来进行类型推导、占用内存空间计算等

查看源码:

 add_rvalue_reference:是C++标准库中的类模板,他的能力是给进一个类型,它能够返回该类型的右值引用类型。

  1. 给进一个int类型,返回的是int&&

  2. 给进一个int&类型,返回的还是int&,这里用到引用折叠

  3. 给进一个int&&类型,返回的是int&&类型,依旧用到引用折叠

std::declval的功能:返回某个类型T的右值引用,不管该类型是否有默认构造函数或者该类型是否可以创建对象,返回某个类型T的右值引用,这个动作是在编译时完成的,所以很多人把std::declval也称为编译时工具

 

namespace nmsp1 {
    class A {
    public:
        //构造函数
        A(int i) {
            printf("A::A()函数执行了,this=%p\n", this);
        }

        double myfunc() {
            printf("A::myfunc()函数执行了,this=%p", this);
            return 12.1;
        }
    };
}


using YT = decltype(std::declval<nmsp1::A>());//这里注意不要把std::declval<nmsp1::A>后面的圆括号丢掉,否则代码含义发生变化

//利用boost输出类型名比typeid(...).name()用法输出类型更准确
using boost::typeindex::type_id_with_cvr;
cout << "YT = " << type_id_with_cvr<YT>().pretty_name() << endl;//显示YT类型
//YT = class nmsp1::A &&

如果有需求需要得到myfunc的返回类型

  • 传统做法:必须创建一个对象
nmsp1::A myaobj(1);
using boost::typeindex::type_id_with_cvr;
cout << "myaobj.myfunc的返回类型 = " << type_id_with_cvr<decltype(myaobj.myfunc())>().pretty_name() << endl;
//A::A()函数执行了,this=003CF8C7
// myaobj.myfunc的返回类型 = double
//如果myfunc函数权限为私有,此时不可以获取
  • 不想创建对象获取到实际类型
using boost::typeindex::type_id_with_cvr;
cout << "A::myfunc的返回类型 = " << type_id_with_cvr<decltype(std::declval<nmsp1::A>().myfunc())>().pretty_name() << endl;
//A::myfunc的返回类型 = double

nmsp1::A&& ayinobj();//看起来是一个函数声明的语法,该函数返回的类型是A&&,可以看成返回一个A&&类型的对象,这种对象可以看成类A对象
//ayinobj();//看起来像调用ayinobj这个函数
//编译没错,链接不行
//ayinobj().myfunc();//同样纯编译没错

decltype(ayinobj().myfunc())  mydblvar;//定义一个double类型的变量mydblvar
//编译链接没错了

 

因为decltype推断类型时是不需要真的调用这个函数,也不需要调用A的myfunc,既然不需要调用,就没必要提供这种函数的函数体

sdt::declval

1.从类型转换的角度来说,将任意一个类型转换成右值引用类型

2.从假想创建出某类型对象的角度来说,配合decltype,令在decltype表达式中,不必经过该类型的构造函数就能使用该类型的成员函数

3.注意:std::declval不能调用,也不能创建任何对象,但std::declval能在不创建对象的情况下,达到创建了一个该类型对象的效果或者说程序员可以假定创建一个该类型的对象

 

std::declval为什么返回右值引用类型

  • 返回类型本身是不好的
namespace nmsp2 {
    template<typename T>
    T mydeclval()noexcept;  //这里返回T
}


using boost::typeindex::type_id_with_cvr;
cout<<"mydeclval()的返回类型 = "<<type_id_with_cvr<decltype(nmsp2::mydeclval<nmsp1::A>())>().pretty_name() << endl;

cout << "mydeclval().myfunc的返回类型 = " << type_id_with_cvr<decltype(nmsp2::mydeclval<nmsp1::A>().myfunc())>().pretty_name() << endl;
//mydeclval()的返回类型 = class nmsp1::A
//mydeclval().myfunc的返回类型 = double

 

在原来类A的基础上增加私有的析构函数

namespace nmsp1 {
    class A {
    public:
        //构造函数
        A(int i) {
            printf("A::A()函数执行了,this=%p\n", this);
        }

        double myfunc() {
            printf("A::myfunc()函数执行了,this=%p", this);
            return 12.1;
        }

    private:
        ~A()
        {

        }
    };
}

cout<<"mydeclval()的返回类型 = "<<type_id_with_cvr<decltype(nmsp2::mydeclval<nmsp1::A>())>().pretty_name() << endl;

cout << "mydeclval().myfunc的返回类型 = " << type_id_with_cvr<decltype(nmsp2::mydeclval<nmsp1::A>().myfunc())>().pretty_name() << endl;//error:无法访问私有的析构函数


cout << "sizeof(mydeclval<A>()) = " << sizeof(nmsp2::mydeclval<nmsp1::A>()) << endl;//error
//因为返回类型本身导致为了遵循语义限制,编译器内部创建了临时的A类对象
//为了绕开予以限制,再设计mydeclval函数模板是,就不要返回T,可以返回T&,也可以返回T&&,
//这样从遵循予以限制方面来说,就不会创建临时的A类对象,这就是返回左值引用右值引用的好处

//上处修改成引用就没有报错
namespace nmsp2 {
    template<typename T>
    T& mydeclval()noexcept;  //这里返回T
}

返回左值引用还是右值引用

class A {
public:
    //构造函数
    A(int i) {
        printf("A::A()函数执行了,this=%p\n", this);
    }

    double myfunc() {
        printf("A::myfunc()函数执行了,this=%p", this);
        return 12.1;
    }

private:
    ~A()
    {

    }
};

template<typename T>
T& mydeclval()noexcept;  

using boost::typeindex::type_id_with_cvr;
cout << "decltype(mydeclval<A>())的返回类型 = " << type_id_with_cvr<decltype(mydeclval<A>())>().pretty_name() << endl;

cout << "decltype(mydeclval<A&>())的返回类型 = " << type_id_with_cvr<decltype(mydeclval<A&>())>().pretty_name() << endl;

cout << "decltype(mydeclval<A&&>())的返回类型 = " << type_id_with_cvr<decltype(mydeclval<A&&>())>().pretty_name() << endl;
//decltype(mydeclval<A>())的返回类型 = class A&
//decltype(mydeclval<A&>())的返回类型 = class A&
//decltype(mydeclval<A&&>())的返回类型 = class A&

 

 

template<typename T>
T&& mydeclval()noexcept; 

using boost::typeindex::type_id_with_cvr;
cout << "decltype(mydeclval<A>())的返回类型 = " << type_id_with_cvr<decltype(mydeclval<A>())>().pretty_name() << endl;

cout << "decltype(mydeclval<A&>())的返回类型 = " << type_id_with_cvr<decltype(mydeclval<A&>())>().pretty_name() << endl;

cout << "decltype(mydeclval<A&&>())的返回类型 = " << type_id_with_cvr<decltype(mydeclval<A&&>())>().pretty_name() << endl;

//decltype(mydeclval<A>())的返回类型 = class A &&
//decltype(mydeclval<A&>())的返回类型 = class A &
//decltype(mydeclval<A&&>())的返回类型 = class A &&

看上面的结果不难想象为啥标注库使用的是返回右值,返回右值拿到的类型更全面

调用引用限定符修饰的成员函数范例

class ALR {
public:
    void onArryValue() {
        cout << "ALR::onArryValue()函数执行了" << endl;
    }

    void oLvalue()& //只能被类ALR的左值对象调用
    {
        cout << "ALR::oLvalue()函数执行l" << endl;

    }

    void oRvalue()&& //只能被类ALR的右值对象调用
    {
        cout << "ALR::oRvalue()函数执行l" << endl;

    }
};

template<typename T>
//T& mydeclval()noexcept;  
T&& mydeclval()noexcept;


ALR alr;    //左值对象alr
alr.oLvalue();
//alr.oRvalue();//无法将左值绑定到右值引用
ALR().oRvalue();//这是临时对象,也是右值对象


decltype(mydeclval<ALR>().onArryValue());
decltype(mydeclval<ALR&>().oLvalue());
decltype(mydeclval<ALR&&>().oRvalue());

//如果
template<typename T>
T& mydeclval()noexcept; 

decltype(mydeclval<ALR&&>().oRvalue());//Error

 

推导函数返回值范例

namespace nmsp2 {
    int myfunc(int a, int b)//函数类型一般由函数的返回值和参数决定
    {
        return a + b;
    }

    template<typename T_F,typename... U_Args>
    decltype(std::declval<T_F>()(std::declval<U_Args>()...)) TestFnRtnImpl(T_F func, U_Args... args)
    {
        //decltype(std::declval<T_F>()(std::declval<U_Args>()...))的作用:根据函数类型以及函数参数类型推断函数返回值类型
        auto rtnvalue = func(args...);
        return rtnvalue;
    }
}

auto result = nmsp2::TestFnRtnImpl(nmsp2::myfunc, 5, 8);//T_F = int (*)(int,int)
cout << result << endl;

int (*fp_var)(int x, int y);//函数指针类型fp_var = int(*)(int,int)
int(*&&refer_fp_var)(int x, int y) = std::move(fp_var);//函数指针的右值引用,int (*&&)(int,int)

fp_var = nmsp2::myfunc;
cout << fp_var(1, 2) << endl;
cout << refer_fp_var(1, 2) << endl;

T_F = int (*)(int,int)类型,也就是函数指针类型

decltype(std::declval<T_F>()(std::declval<U_Args>()…)) = int ,也就是myfunc的返回类型

decltype(std::declval<T_F>()) = 是int (*&&)(int,int)函数指针的右值引用类型,decltype(std::declval<U_Args>()…)这种写法:推导出来的是两个int&&

namespace nmsp3 {
    //返回类型后置语法
    template<typename T_F, typename... U_Args>
    auto TestFnRtnImpl(T_F func, U_Args... args)->decltype(func(args...))
    {   //->decltype(func)  int(*)(int,int)
        auto rtnvalue = func(args...);
        return rtnvalue;
    }
}

 

https://blog.csdn.net/m0_51271123/article/details/121780256

标签:std,返回,decltype,declval,int,c++,-----,类型
From: https://www.cnblogs.com/bwbfight/p/18189207

相关文章

  • 消费电子产品数据安全芯片推荐-LCS4110R
    这些年来,我国消费电子的技术一直都在不断上升,很多知名品牌的消费电子都把生产基地建立在我国,成为了全球最大的消费电子的制造中心。同时我国消费电子的市场规模也在不断增大,这也让市场成熟度提高。我国不仅是最大的消费电子消费国,也是出口国。如何保障消费电子的版权及数据安全,可......
  • 4-30V 输入、1.2A 固定输出同步降压驱动器
    产品描述 AP3462是一款支持宽电压输入的同步降压电源管理芯片,输入电压4-30V范围内可实现1.2A的连续电流输出。AP3462具有优秀的恒压特性。AP3462采用电流模式的环路控制原理,实现了快速的动态响应。AP3462工作开关频率为220kHz,具有良好的EMI特性。AP3462内置有......
  • OpenSSL测试-SM4
    任务详情:0.在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务,参考别人代码要给出链接,使用AI工具要给出过程,否则成绩归零。1.使用OpenSSL的命令对你的8位学号(字符串)进行加密解密,密钥的前8个字节为你的8位学号,提交过程截图(5')2.使用OpenSSL编程对对"你的8位学号(数字)"进......
  • VMware vSphere Bitfusion 4.5.4 - 面向 AI 和 ML 应用提供弹性基础架构
    VMwarevSphereBitfusion4.5.4-面向AI和ML应用提供弹性基础架构请访问原文链接:VMwarevSphereBitfusion4.5.4-面向AI和ML应用提供弹性基础架构,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgVMwarevSphereBitfusion4.5|23NOV2021|Build4......
  • VMware Avi Load Balancer 30.2.1 发布 - 多云负载均衡平台
    VMwareAviLoadBalancer30.2.1发布-多云负载均衡平台应用交付:多云负载均衡、Web应用防火墙和容器Ingress服务请访问原文链接:VMwareAviLoadBalancer30.2.1-多云负载均衡平台,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org负载均衡平台VMwareAviLoa......
  • VMware NSX Advanced Load Balancer (NSX ALB) 30.2.1 - 多云负载均衡平台
    VMwareNSXAdvancedLoadBalancer(NSXALB)30.2.1-多云负载均衡平台应用交付:多云负载均衡、Web应用防火墙和容器Ingress服务请访问原文链接:VMwareNSXAdvancedLoadBalancer(NSXALB)30.2.1-多云负载均衡平台,查看最新版。原创作品,转载请保留出处。作者主页:sysin......
  • PyAlgoTrade-0-20-中文文档-一-
    PyAlgoTrade0.20中文文档(一)介绍原文:gbeced.github.io/pyalgotrade/docs/v0.20/html/intro.htmlPyAlgoTrade是一个支持事件驱动的算法交易Python库,支持:使用来自CSV文件的历史数据进行回测。使用Bitstamp实时数据进行模拟交易。在Bitstamp上进行真实交易。......
  • PyAlgoTrade-0-20-中文文档-四-
    PyAlgoTrade0.20中文文档(四)SMA交叉原文:gbeced.github.io/pyalgotrade/docs/v0.20/html/sample_sma_crossover.html将此代码保存为sma_crossover.py:frompyalgotradeimportstrategyfrompyalgotrade.technicalimportmafrompyalgotrade.technicalimportcrosscl......
  • PyAlgoTrade-0-20-中文文档-三-
    PyAlgoTrade0.20中文文档(三)工具原文:gbeced.github.io/pyalgotrade/docs/v0.20/html/tools.htmlQuandlpyalgotrade.tools.quandl.``build_feed(sourceCode,tableCodes,fromYear,toYear,storage,frequency=86400,timezone=None,skipErrors=False,authToken=None,columnNames={......
  • PyAlgoTrade-0-20-中文文档-二-
    PyAlgoTrade0.20中文文档(二)经纪人-订单管理类原文:gbeced.github.io/pyalgotrade/docs/v0.20/html/broker.html基础模块和类类pyalgotrade.broker.``Order(type_,action,instrument,quantity,instrumentTraits)基类:object订单的基类。参数:type(Order.Type)–订单类......