C++ Idiom - Return Type Resolver (返回类型自动解析)

本文记录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;
}

运行结果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值