本文记录C++编程习语中的返回类型自动解析法则,避免变量类型的重复声明
代码地址:https://github.com/pengguoqing/samples_code/tree/master/c%2B%2B/idiom/returnTypeResolver
一、类型重复声明问题
1.1 函数重载或者函数模板
假如我们要实现字符串转数值类型的功能,可能的想法如下:
//①重载函数,此时编译器会报错。因为不能通过函数返回值类型来重载函数
int from_string(const char *str) { return std::stoi(str); }
float from_string(const char *str) { return std::stof(str); }
// ②函数模板
template<class T>
T FromString(const char* str)
{
if (std::is_same<T, int>::value)
{
return std::stoi(str);
}
else if (std::is_same<T, float>::value)
{
return std::stof(str);
}
return T{};
}
调用如下:
int valuei = FromString<int>("666");
float valuef = FromString<float>("6.66");
此时假如打印的话,控制台能输出 整型的 666 和 浮点型的 6.66。
1.2 模板类
模板类中也存在相似的问题,比如要实现一个对不同的标准库容器随机赋值的功能,可能的实现如下:
template <class Container>
Container GetRange(size_t from, size_t to)
{
Container c;
for (size_t i = from; i < to; ++i)
c.insert(c.end(), i);
return c;
}
调用如下:
std::list<int> colist = GetRange<std::list<int> >(3, 6);
std::vector<long> covector = GetRange<std::vector<long>>(6, 9);
此时, 无论是模板类还是函数模板初始化变量的类型信息都需要传递给被调用者。此时面临的问题就是这个类型被重复了两次,一次用来声明,一次用来调用。C++习语中的返回类型解析器就用来解决这个问题的。
二、解决方案
返回类型解析器的实现方法是利用一个代理类,并且模板化类的类型转换操作符函数,最后再利用编译器的自动类型推导来实现。以上两种问题的解决方案分别如下:
class CXFromString
{
public:
CXFromString(const char* str)
:m_str{str}
{}
operator int()
{
return std::stoi(m_str);
}
operator float()
{
return std::stof(m_str);
}
private:
const string m_str;
};
class CXRange
{
public:
CXRange(const size_t from, const size_t to): from{from}, to{to}
{ }
template<typename Container>
operator Container()
{
Container container;
for(size_t i = from; i < to; ++i)
container.insert(container.end(), i);
return container;
}
private:
const size_t from, to;
};
测试代码如下:
int main(int argc, char** argv)
{
int valuei = CXFromString("666");
float valuef = CXFromString("6.66");
cout<< valuei <<endl;
cout<< valuef <<endl;
std::vector<int> veci = CXRange(0, 3);
for(const auto& item : veci)
std::cout << item << std::endl;
std::list<int> listf = CXRange(3, 6);
for(const auto&item : listf)
std::cout << item << std::endl;
return 0;
}
运行结果如下: