首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

C++之std::declval

  • 24-03-18 06:43
  • 4481
  • 5195
blog.csdn.net

相关系列文章

C++之std::is_object

C++之std::decay

C++模板函数重载规则细说

C++之std::declval

C++之std::move(移动语义)

C++之std::forward(完美转发)

C++之std::enable_if

C++之std::is_pod(平凡的数据)

目录

1.简介

2.用法

2.1.在实际使用用时,std::declval一般结合decltype使用

2.2.在函数模板和类模板中推导参数的类型和返回值的类型

2.3.std::declval还可以用来判断某个类是否具备某个成员函数

3.参考


1.简介

std::declval是C++11引入的一个模板函数,将任意类型 T 转换成右值引用&&类型,在 decltype 表达式中不必经过构造函数就能使用成员函数;通常在模板中使用 std::declval时,模板接受的模板实参通常可能无构造函数,但有同一成员函数,均返回所需类型。

在VS2019中函数的原型:

  1. template <class _Ty>
  2. add_rvalue_reference_t<_Ty> declval() noexcept;

通过 add_rvalue_reference_t 返回模板类型_Ty的右值引用_Ty&&,   add_rvalue_reference_t的定义如下:

add_rvalue_reference_t是C++标准中模板类,它是将传入的模板类_Ty转换为_Ty&&, 即返回它的又值引用类型,如:

        1) 如果_Ty是int, 根据引用折叠规则和上面A定义返回的就是int&&类型

        2) 如果_Ty是int&,根据引用折叠规则第上面B定义返回的就是int&&类型

        3) 如果_Ty是int&&,根据引用折叠规则和上面A定义返回的就是int&&类型

2.用法

2.1.在实际使用用时,std::declval一般结合decltype使用

  1. //调用引用限定符修饰的成员函数
  2. class ALR
  3. {
  4. public:
  5. void onAnyValue()
  6. {
  7. qDebug() << "ALR::onAnyValue()函数执行了!" << endl;
  8. }
  9. void onLvalue()& //只能被类ALR的左值对象调用
  10. {
  11. qDebug() << "ALR::onLvalue()函数执行了!" << endl;
  12. }
  13. void onRvalue()&& //只能被类ALR的右值对象调用
  14. {
  15. qDebug() << "ALR::onRvalue()函数执行了!" << endl;
  16. }
  17. };
  18. template <typename T>
  19. T&& mydeclval() noexcept;
  20. int main() {
  21. ALR alr; //左值对象alr
  22. alr.onLvalue();
  23. //alr.onRvalue(); //编译错误,因为onRvalue只能被类A的右值对象调用
  24. ALR().onRvalue(); //临时对象是右值对象
  25. //ALR().onLvalue(); //编译错误,因为onLvalue只能被类A的左值对象调用
  26. decltype(mydeclval().onAnyValue());
  27. decltype(mydeclval().onLvalue()); //返回的 类型是class ALR &,代表返回的是左值对象,左值对象调用onLvalue没问题
  28. decltype(mydeclval().onRvalue()); //返回的 类型是class ALR &&,代表返回的是右值对象,右值对象调用onRvalue没问题
  29. //decltype(mydeclval().onRvalue());//返回的 类型是class ALR &,代表返回的是左值对象,左值对象调用onRvalue是错误的
  30. //decltype(mydeclval().onLvalue()); //返回的 类型是class ALR &&,代表返回的是右值对象,右值对象调用onLvalue是错误的
  31. return 0;
  32. }

decltype(mydeclval().onAnyValue()) 、decltype(mydeclval().onLvalue())和decltype(mydeclval().onRvalue()) 不会调用onAnyValue函数,也不会调用onLvalue函数和onRvalue函数,所以不会报错。

同理,可理解decltype(std::declval().onAnyValue())含义,同样它也不会调用ALR的onAnyValue函数。

2.2.在函数模板和类模板中推导参数的类型和返回值的类型

如:

  1. template <typename T>
  2. class CMessageEntityManagerTemplate
  3. {
  4. //方法1
  5. //using KEY = decltype(((T*)0)->id());
  6. //方法3
  7. using KEY = decltype(std::declval().id());
  8. ...
  9. ...
  10. }

模板类CMessageEntityManagerTemplate中的数据类型KEY通过T.id()函数在编译时期推导出的,而不会去调用id()函数的。

再比如:

  1. #include
  2. #include
  3. struct Default { int foo() const { return 1; } };
  4. struct NonDefault
  5. {
  6. NonDefault() = delete;
  7. int foo() const { return 1; }
  8. };
  9. int main()
  10. {
  11. decltype(Default().foo()) n1 = 1; // n1 的类型是 int
  12. // decltype(NonDefault().foo()) n2 = n1; // 错误:无默认构造函数
  13. decltype(std::declval().foo()) n2 = n1; // n2 的类型是 int
  14. std::cout << "n1 = " << n1 << '\n'
  15. << "n2 = " << n2 << '\n';
  16. return 0;
  17. }

输出:

  1. n1 = 1
  2. n2 = 1

从这个例子可以看出,std::declval不管传入对象 NonDefault 是否可以构造,都不会报错,那是因为std::declval返回的是NonDefault&&,从而避免了返回 NonDefault 时编译器内部不能创建临时对象导致编译报错的发生。

2.3.std::declval还可以用来判断某个类是否具备某个成员函数

  1. #define HAS_MEMBER_EX(member)\
  2. template struct has_member_ex_##member{\
  3. private:\
  4. template \
  5. static auto Check(int) -> decltype(U::member(std::declval()...), std::true_type()); \
  6. template \
  7. static std::false_type Check(...); \
  8. public:\
  9. enum { value = std::is_same(0)), std::true_type>::value }; \
  10. }; \
  11. HAS_MEMBER_EX(getDataSize)

调用方法:

  1. template typename stType>
  2. int parseCommonCmdData(const char* data, int len, stShortWavePacket* pPacket)
  3. {
  4. ...
  5. if constexpr (has_member_ex_getDataSize::value) {
  6. if (length != stType::getDataSize())
  7. return -1;
  8. }
  9. ...
  10. }

这里条件判断必须加上constexpr,因为这个条件判断是在编译的时候发生的。

3.参考

<<深入应用C++11代码优化与工程级应用>>

注:本文转载自blog.csdn.net的流星雨爱编程的文章"https://blog.csdn.net/haokan123456789/article/details/135088052"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top