c++ - 重载(期望的)返回类型
问题描述
to_string
为您自己的类型定义一个函数很容易,并且只需通过重载来调用它。大部分代码都知道to_string(x)
将通过 ADL 找到的约定,模板可以依赖它而不知道x
.
但是相反的情况呢,比如from_string
函数呢?什么是类型提供自己的实现的好方法,以便其他代码可以轻松方便地调用它,并且它也可以在模板中工作?
当这些实现本身对某些类型是通用的时,为每种类型使用具有显式特化的单个模板会让人头疼。(至少,在概念之前的实现中是这样。)
使所需的类型出现在参数列表中,无论是作为虚拟参数还是通过包装输入字符串的模板类型,其优点是函数的选择使用适当的重载分辨率,并且可以简单自然地在不同的实现之间进行选择,包括普通单类型函数、处理一组相关类型的模板、隐式转换和继承关系。
虽然它适用于通用代码,但调用起来很尴尬,我不想让它成为调用它的正常方式。
我的项目使用 gcc 8,它支持 C++17 和 Concepts TS。标准库对概念一无所知,但我可以requires
在自己的代码中使用和创建概念。
定义这样的函数的好方法是from_string
什么?
解决方案
要支持模板类,您需要一个可以专门化的结构。
template<class T, class sfinae=void> struct from_string_impl;
然后是一个辅助方法和类型来调用它operator()
:
struct from_string_t {
const std::string& str;
template<class T>
operator T() const {return from_string_impl<T>{}(str);}
};
from_string_t from_string(const std::string& str) {return {str};}
还有一些基本的启动器实现:
template<> struct from_string_impl<int>{int operator()(const std::string& str) { return std::stoi(str);}};
template<> struct from_string_impl<long>{long operator()(const std::string& str) { return std::stol(str);}};
template<> struct from_string_impl<long long>{long long operator()(const std::string& str) { return std::stoll(str);}};
template<> struct from_string_impl<unsigned long>{unsigned long operator()(const std::string& str) { return std::stoul(str);}};
template<> struct from_string_impl<unsigned long long>{unsigned long long operator()(const std::string& str) { return std::stoull(str);}};
template<> struct from_string_impl<float>{float operator()(const std::string& str) { return std::stof(str);}};
template<> struct from_string_impl<double>{double operator()(const std::string& str) { return std::stod(str);}};
template<> struct from_string_impl<long double>{long double operator()(const std::string& str) { return std::stold(str);}};
在大多数情况下使用是微不足道的:
int i = from_string("304.5");
double d = from_string("304.5");
unsigned long long ull = from_string("304.5");
http://coliru.stacked-crooked.com/a/d4bd08dbe081a156
尽管如果您尝试将其传递给本身具有重载的方法,则会出现编译器错误,因为编译器将无法推断将返回类型转换为哪种类型。
有趣的是,这可以追溯到模板首次添加到 C++ 时的效果。
推荐阅读
- sql - 从表中捕获值并在 SQL 函数中声明为局部变量
- terraform - Terraform 动态生成属性(不是块)
- bouncycastle - 在 .net5 中使用证书
- scala - Spark : 我如何找到一起乘坐超过 3 个航班的乘客
- python - Pytest 捕获某个测试的标准输出
- discord - 我如何使用 Discord 机器人踢人?
- javascript - 如何在 ReactJS Hooks 中将数据添加到对象的末尾
- css - 我应该为现有的 HTML 颜色名称使用 CSS 变量吗
- python - 如何在一张图上叠加每天的时间序列
- sql - SQL 查询 - 使用 ALL 和 '=' 运算符未获得预期结果