上一篇介绍了支持C++类型的格式化操作,但还是存在以下缺点:
- 1、非类型安全,必须提供正确的%s、%d、%f等类型符号,否则有可能造成程序崩溃。
- 2、部分参数如果存在多次重复的情况下,需要多次指定参数。
针对以上缺点,我希望提供更加简洁的格式化操作函数以供选择:
format_pos("%1 + %2 = %3", 1,2,"3")
测试代码:
class TestPrint
{
public:
    TestPrint()
    {
        std::cout << "TestPrint 构造函数" << std::endl;
    }
    ~TestPrint()
    {
        std::cout << "TestPrint 析构函数" << std::endl;
    }
    friend void operator << (std::iostream& out, const TestPrint& t)
    {
        out << t.val << "_" << t.a ;
    }
private:
    int a = 100;
    std::string val = "hello";
};
int main()
{
    std::string strMsg("my msg");
    std::cout << format_pos("this is %1 --> %2, this is %1 --> %2", strMsg, TestPrint()) << std::endl;
    return 0;
}实现代码:
//参数包装,统一转化成Param类
template<typename T>
std::string Param(T& val)
{
	std::stringstream str;
	str << val;
	return str.str();
};
//特化
template<typename T = std::string>
std::string& Param(std::string& val)
{
	return val;
};
//特化
template<typename T = const char*>
std::string Param(const char* val)
{
	return val;
};
//参数搜集器,负责收集参数,并将参数格式化输出
class VCollect
{
public:
	VCollect(const char* pszContext) :m_pszContext(pszContext)
	{
	}
	//递归结束,将结果返回
	std::string PosFormat()
	{
		return GetString();
	}
	template<typename T, typename ...Args>
	std::string PosFormat(T val, Args...args)
	{
		m_vecParam.emplace_back(Param(val));
		return PosFormat(args...);
	}
	std::string GetString()
	{
		std::stringstream str;
		const char* s = m_pszContext;
		while (*s)
		{
			if (*s == '%')
			{
				char ch = atoi(++s);
				if (ch == '%')
				{
					str << *s;
					continue;
				}
				int nArgNum = atoi(s++);
				if (nArgNum <= 0 || nArgNum > m_vecParam.size())
				{
					return str.str();
				}
				str << m_vecParam[nArgNum - 1];
				while ((nArgNum = nArgNum / 10) > 0)s++;
			}
			else
			{
				str << *s++;
			}
		}
		return std::move(str.str());
	}
private:
	std::vector<std::string> m_vecParam;
	const char* m_pszContext;
};
//按占位符替换参数,使用方法  format_pos("%1 + %2 = %3", 1,2,"3")
template<typename...Args>
std::string format_pos(const char *strFmt, Args...args)
{
    return VCollect(strFmt).PosFormat(args...);
}
//特化,实现未带参数场景
std::string format_pos(const char *strFmt)
{
    return strFmt;
}
来源:oschina
链接:https://my.oschina.net/u/3312209/blog/4305222