我是可变参数模板函数的新手。我编写了一个简单的类StringStream
,该类具有可变模板函数,该函数根据变量模板参数(字符串,整数等)创建一个std::string
。
#include <string>
#include <sstream>
class StringStream
{
public:
StringStream() = default;
~StringStream() = default;
template<typename T>
std::string Stringify(const T &value)
{
mStream << value;
return mStream.str();
}
template<typename T, typename... Ts>
std::string Stringify(const T& value, Ts... values)
{
mStream << value;
return Stringify(values...);
}
private:
std::stringstream mStream;
};
我现在想要做的是在std::string
中使用StringStream
成员而不是std::stringstream
,然后根据Stringify()
的参数构建字符串。对于非std::string
的参数,我想使用std::to_string()
转换为字符串,否则我将串联该参数。我遇到编译器错误。这是我修改过的课程:
class StringStream
{
public:
StringStream() = default;
~StringStream() = default;
template<typename T>
std::string Stringify(const T &value)
{
mString += std::to_string(value);
return mString;
}
template<>
std::string Stringify<std::string>(const std::string& value)
{
mString += value;
}
template<typename... Ts>
std::string Stringify(const std::string& value, Ts... values)
{
mString += value;
return Stringify(values...);
}
template<typename T, typename... Ts>
std::string Stringify(const T& value, Ts... values)
{
mString += std::to_string(value);
return Stringify(values...);
}
private:
std::string mString;
};
我的编译器错误说:
错误C2665:“ std :: to_string”:这9个重载都无法转换所有参数类型
我正在这样调用函数:
int main()
{
int age;
std::cin >> age;
StringStream ss;
std::cout << ss.Stringify("I", " am ", age, " years ", "old") << std::endl;
}
有什么办法解决这个问题?
答案 0 :(得分:2)
错误的原因是,字符串文字("I"
," am "
," years "
,"old"
)是常数char
s({ {1}}(对于某些char const [N]
)。您可以将其拦截为N
,而不能拦截为char const *
。
我想这有点偏离主题,但是我给你两个建议:
(1)将std::string
划分为两个函数:可变参数Stringify()
,该函数调用public
一个(在下面的示例中为private
)进行转换超过单打参数
(2)避免对toStr()
的可变版本进行递归,而只需使用包扩展。
我的意思是...您可以按如下方式写Stringify()
Stringify()
或者,如果可以使用C ++ 17,请使用模板折叠
template <typename... Ts>
std::string Stringify (Ts const & ... vals)
{
using unused = int[];
(void)unused { 0, (mString += toStr(vals), 0)... };
return mString;
}
对于 template <typename... Ts>
std::string Stringify (Ts const & ... vals)
{ return ((mString += toStr(vals)), ...); }
,我建议使用toStr()
的模板版本,但仅在模板std::to_string()
类型不能转换为T
std::string
以及接受 template <typename T>
typename std::enable_if<
false == std::is_convertible<T, std::string>::value,
std::string>::type toStr (T const & val)
{ return std::to_string(val); }
std::string
这样,如果参数可以直接转换为 std::string toStr (std::string const & val)
{ return val; }
(是std::string
或可以用来构造std::string
的其他类型),则称为非模板版本;否则称为模板一。
以下是完整的编译示例
std::string
答案 1 :(得分:1)
您正在内部致电to_string
template<typename T>
std::string Stringify(const T &value)
{
mString += std::to_string(value);
return mString;
}
因此您可以从to_string
中删除Stringify(const T& value, Ts... values)
,并仅用Stringify
代替:
template<typename T, typename... Ts>
std::string Stringify(const T& value, Ts... values)
{
mString += Stringify(value);
return Stringify(values...);
}
还为const char *添加了特殊化:
std::string Stringify(const char* value)
{
return mString += value;
}
现在您的问题是const char[2]
传递了to_string
,但是to_string
没有接受该输入的重载。通过将to_string
替换为Stringify
,可以将适当的重载用于参数包中的第一个参数。