首页 > 解决方案 > 重载(期望的)返回类型

问题描述

to_string为您自己的类型定义一个函数很容易,并且只需通过重载来调用它。大部分代码都知道to_string(x)将通过 ADL 找到的约定,模板可以依赖它而不知道x.

但是相反的情况呢,比如from_string函数呢?什么是类型提供自己的实现的好方法,以便其他代码可以轻松方便地调用它,并且它也可以在模板中工作?

当这些实现本身对某些类型是通用的时,为每种类型使用具有显式特化的单个模板会让人头疼。(至少,在概念之前的实现中是这样。)

使所需的类型出现在参数列表中,无论是作为虚拟参数还是通过包装输入字符串的模板类型,其优点是函数的选择使用适当的重载分辨率,并且可以简单自然地在不同的实现之间进行选择,包括普通单类型函数、处理一组相关类型的模板、隐式转换和继承关系。

虽然它适用于通用代码,但调用起来很尴尬,我不想让它成为调用它的正常方式。

我的项目使用 gcc 8,它支持 C++17 和 Concepts TS。标准库对概念一无所知,但我可以requires在自己的代码中使用和创建概念。

定义这样的函数的好方法是from_string什么?

标签: c++c++17c++20

解决方案


要支持模板类,您需要一个可以专门化的结构。

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++ 时的效果。


推荐阅读