当前位置: 首页 > news >正文

无用知识研究:在trailing return type利用decltype,comma operator在对函数进行sfinae原创 [三]

感觉利用返回类型后置的写法,比在函数的参数列表里加参数,要方便很多。

template<typname T, std::enable_if_t<std::is_floating_v<T>,int>*=0>

void fun(T&& t)

{

}

只有一个函数的版本,只匹配floating:

注意:
std::enable_if_t<std::is_floating_point_v<std::remove_reference_t<T>>, int>(),的写法,
它不仅促使编译器进行substitution,也deduce出了一个类型:int。所以让函数模板
的“重载”带有sfinae的功能。1、如果写成std::is_floating_point_v<std::remove_reference_t<T>>,可能可以编译成功,但匹配时可能有substitution,但没有deduce,所以可以编译成功,但匹配的可能不对。
2、如果把()写成{},也就是写成std::enable_if_t<std::is_floating_point_v<std::remove_reference_t<T>>, int>{},
也会出现:编译成功,但其实匹配不对的问题。#include <iostream>
#include <string>
#include <type_traits>
#include <iostream>
#include <functional>/////////////////////////
// 过滤是否为floating类型
/////////////////////////
template<typename T>
auto check_double_and_return(T&& t) -> decltype(std::enable_if_t<std::is_floating_point_v<std::remove_reference_t<T>>, int>(),// 逗号表达式的第二个(最后一个)部分:决定函数返回类型的表达式std::forward<T>(t))
{std::cout << "is floating" << std::endl;return std::forward<T>(t);
}int main()
{int x = 42;const std::string& str = "test";///////////////////////////// 检查double///////////////////////////double f = 1.0;//static_assert(!std::is_floating_point_v<std::remove_reference_t<double>>, "Type cannot be double!"),//std::cout << check_double_and_return(f) << std::endl;std::cout << check_double_and_return(x) << std::endl; //这行编译错误,符合预期,而且也没有默认的函数满足sfinae,所以只能编译报错}编译错误信息:
error C2672: “check_double_and_return”: 未找到匹配的重载函数
error C2893: 未能使函数模板“unknown-type check_double_and_return(T &&)”专用化
note: 用下列模板参数:
note: “T=int &”

除了floating,还增加一个检验class的版本:

#include <iostream>
#include <string>
#include <type_traits>
#include <iostream>
#include <functional>/////////////////////
// 匹配浮点数的变量
/////////////////////
template<typename T>
auto check_double_and_return(T&& t) -> decltype(// 逗号表达式的第一个部分:一个编译期断言///*static_assert*/(!std::is_floating_point_v<std::remove_reference_t<T>>, "Type cannot be floating!"),std::enable_if_t<std::is_floating_point_v<std::remove_reference_t<T>>, int>(),// 逗号表达式的第二个(最后一个)部分:决定函数返回类型的表达式std::forward<T>(t))
{std::cout << "is floating" << std::endl;return std::forward<T>(t);
}/////////////////////
// 匹配class类型的变量
/////////////////////
template<typename T>
auto check_double_and_return(T&& t) -> decltype(// 逗号表达式的第一个部分:一个编译期断言///*static_assert*/(!std::is_floating_point_v<std::remove_reference_t<T>>, "Type cannot be floating!"),std::enable_if_t<std::is_class_v<std::remove_reference_t<T>>, int>(),// 逗号表达式的第二个(最后一个)部分:决定函数返回类型的表达式std::forward<T>(t))
{std::cout << "is class" << std::endl;return std::forward<T>(t);
}class CTest
{};int main()
{int x = 42;const std::string& str = "test";///////////////////////////// 检查double///////////////////////////double f = 1.0;//static_assert(!std::is_floating_point_v<std::remove_reference_t<double>>, "Type cannot be double!"),//auto v = check_double_and_return(f); //匹配上第一个std::cout << v << std::endl;//std::cout << check_double_and_return(x) << std::endl;CTest o;check_double_and_return(o); //匹配上第二个
}运行结果:
is floating
1
is class

来一个sfinae版的,当既不匹配floating,又不匹配class的情况:

#include <iostream>
#include <string>
#include <type_traits>
#include <iostream>
#include <functional>template<typename T>
auto check_double_and_return(T&& t) -> decltype(// 逗号表达式的第一个部分:一个编译期断言///*static_assert*/(!std::is_floating_point_v<std::remove_reference_t<T>>, "Type cannot be floating!"),std::enable_if_t<std::is_floating_point_v<std::remove_reference_t<T>>, int>(),// 逗号表达式的第二个(最后一个)部分:决定函数返回类型的表达式std::forward<T>(t))
{std::cout << "is floating" << std::endl;return std::forward<T>(t);
}template<typename T>
auto check_double_and_return(T&& t) -> decltype(// 逗号表达式的第一个部分:一个编译期断言///*static_assert*/(!std::is_floating_point_v<std::remove_reference_t<T>>, "Type cannot be floating!"),std::enable_if_t<std::is_class_v<std::remove_reference_t<T>>, int>(),// 逗号表达式的第二个(最后一个)部分:决定函数返回类型的表达式std::forward<T>(t))
{std::cout << "is class" << std::endl;return std::forward<T>(t);
}auto check_double_and_return(...) -> void
{std::cout << "is default" << std::endl;}// template<typename T>
// auto check_double_and_return(...) -> void
// {
//     std::cout << "is default" << std::endl;
// }class CTest
{};enum MyEnum
{hhh
};
int main()
{int x = 42;const std::string& str = "test";// 正常工作//std::cout << check_and_return(x) << std::endl;//std::cout << check_and_return(str) << std::endl;// 下面这行会导致编译错误,因为 static_assert 失败//check_and_return(static_cast<void>(x)); //std::cout << check_string_and_return(str) << std::endl;///////////////////////////// 检查double///////////////////////////double f = 1.0;//static_assert(!std::is_floating_point_v<std::remove_reference_t<double>>, "Type cannot be double!"),//auto v = check_double_and_return(f);std::cout << v << std::endl;//std::cout << check_double_and_return(x) << std::endl;CTest o;check_double_and_return(o); //匹配上classcheck_double_and_return(str); //也匹配上classMyEnum e = MyEnum::hhh;check_double_and_return(e); //匹配上默认的
}运行结果:
is floating
1
is class
is class
is default

注意,这些限制里,不能有交集,否则会报error C2668: “check_double_and_return”: 对重载函数的调用不明确。什么叫交集呢,比如一个check_double_and_return里规定需要是一个class,另一个check_double_and_return规定需要是一个class,并且这个class要有emplace_back函数。这种情况下,就会编译报错。

#include <iostream>
#include <string>
#include <type_traits>
#include <iostream>
#include <functional>
#include <vector>template<typename T>
auto check_double_and_return(T&& t) -> decltype(// 逗号表达式的第一个部分:一个编译期断言///*static_assert*/(!std::is_floating_point_v<std::remove_reference_t<T>>, "Type cannot be floating!"),std::enable_if_t<std::is_floating_point_v<std::remove_reference_t<T>>, int>(),// 逗号表达式的第二个(最后一个)部分:决定函数返回类型的表达式std::forward<T>(t))
{std::cout << "is floating" << std::endl;return std::forward<T>(t);
}template<typename T>
auto check_double_and_return(T&& t) -> decltype(// 逗号表达式的第一个部分:一个编译期断言///*static_assert*/(!std::is_floating_point_v<std::remove_reference_t<T>>, "Type cannot be floating!"),std::enable_if_t<std::is_class_v<std::remove_reference_t<T>>, int>(),// 逗号表达式的第二个(最后一个)部分:决定函数返回类型的表达式std::forward<T>(t))
{std::cout << "is class" << std::endl;return std::forward<T>(t);
}template<typename T>
auto check_double_and_return(T&& t) -> decltype(// 逗号表达式的第一个部分:一个编译期断言///*static_assert*/(!std::is_floating_point_v<std::remove_reference_t<T>>, "Type cannot be floating!"),std::enable_if_t<std::is_class_v<std::remove_reference_t<T>>, int>(),t.emplace_back(0),// 逗号表达式的第二个(最后一个)部分:决定函数返回类型的表达式std::forward<T>(t))
{std::cout << "is container" << std::endl;return std::forward<T>(t);
}auto check_double_and_return(...) -> void
{std::cout << "is default" << std::endl;}class CTest
{};enum MyEnum
{hhh
};int main()
{int x = 42;const std::string& str = "test";///////////////////////////// 检查double///////////////////////////double f = 1.0;//static_assert(!std::is_floating_point_v<std::remove_reference_t<double>>, "Type cannot be double!"),//auto t = check_double_and_return(f);std::cout << t << std::endl;//std::cout << check_double_and_return(x) << std::endl;CTest o;check_double_and_return(o); //匹配上classcheck_double_and_return(str); //也匹配上classMyEnum e = MyEnum::hhh;check_double_and_return(e); //匹配上默认的std::vector<int> v;check_double_and_return(v); //编译错误,因为第二个和第三个都符合要求。所以选不出来,删除其中一个就可以编译成功。
}

编译提示如下:

http://www.dtcms.com/a/508959.html

相关文章:

  • 网站首页分类怎么做的wordpress 微博主题 twitter主题
  • 前端学习手册-ECMAScript 6 入门(十四)
  • 网站建设预付款网站设计作业多少钱
  • 怎么注册建设公司网站微信朋友圈产品推广语
  • 河北农业网站建设公司wordpress找回密码邮件
  • 老版建设银行网站做网站设计前景怎么样
  • 爱站网为什么不能用了深圳市建设网络有限公司网站
  • 2025最新可用 百度网盘不限制下载
  • 【医学影像 AI】一种用于生成逼真的3D血管的分层部件生成模型
  • 四级a做爰片免费网站首页八度空间
  • 就业选择,大厂测试还是小厂开发?
  • 哪家网站专门做折扣销售网站底部代码特效
  • 宁波企业网站开发公司和硕网站建设
  • 做神马网站快速排asp.net 网站 价格
  • 郑州高端网站建设外贸网站 有哪些
  • 通用装饰器示例
  • LangChain最详细教程(一)
  • ui设计的网站群晖nda做网站
  • 郑州企业网站设计高端网站建设要多少钱
  • Marin说PCB之SI----做信号完整性仿真时需要注意的地方--03
  • 东莞市住房建设局网站西昌网站建设
  • windows平台,导出数据库
  • 有效的网站推广方案申请域名注册备案平台
  • 如何用Redis实现乐观锁?
  • 商城网站建设公司招聘php+mysql网站开发技术与典型案例导航【源代码】
  • 免费注册个人网站不花钱网站网页设计
  • 滁州网站开发公司电话盐城网站建设找宇
  • gerrit的部署与配置关联到不同服务器上的git仓库
  • Nginx静态网站:从原理到实战
  • 建一个o2o网站网站建设与管理好找工作吗