目前我正在开发一个类似于C#的String.Format(...)
函数的函数,只是在C ++中。 (String.Format(...))
但这不是我的问题。该函数工作正常但有问题的是它需要vector<string>
作为参数,如果我想使用整数作为参数,我必须编写如下代码:
// function prototype, the function body is not relevant here
string format(string str, vector<string> variables);
// ... some context
// i could use to_string() here,
// but imagine a complex type which only overrides the stream operator
int a = 20;
stringstream ss;
ss << a;
string a_str = format("a has the value '{}'", { ss.str() });
这是一些样板代码!
因此,我需要一个将未知数据类型集合转换为vector<string>
的函数。
我尝试过这样的事情:
vector<string> vec_string(vector<void*> args) {
vector <string> result;
for (unsigned i = 0; i < args.size(); i++)
{
stringstream ss;
// I can't dereference an object without knowing to pointer type. :(
ss << *((int*)args[i]);
result.push_back(ss.str());
}
return result;
}
// ... some context
int a = 10;
cout << format("some int: '{}'", vec_string({ (void*) &a }));
这显然只适用于整数,非常不舒服。我觉得这样做的唯一方法是可变参数宏,但我不知道它们是如何工作的。
here是我format(...)
方法的链接。
我很抱歉我的拼写,但我尽力纠正它。
答案 0 :(得分:1)
使用可变参数模板可以相对容易地完成:
template <class T>
auto toString(T&& t) {
std::stringstream s;
s << std::forward<T>(t);
return s.str();
}
template <class... T>
auto toStringVector(T&&... args) {
std::vector<std::string> res {toString(std::forward<T>(args))...};
return res;
}
这会通过std::string
将每个参数转换为stringstream
,然后返回包含所述字符串的std::vector<std::string>
。 (Live example.)
然后您可以按照问题中的预期直接使用,即:
std::cout << format("some text", toStringVector(any, number, of, arguments,
of, any, type));
如果您使用的是Boost,则可以跳过toString
帮助,转而使用boost::lexical_cast
:
template <class... T>
auto toStringVector(T&&... args) {
std::vector<std::string> res { boost::lexical_cast<std::string>(std::forward<T>(args))...};
return res;
}
lexical_cast
很可能在内置类型上更快。
答案 1 :(得分:0)
我想通了,不知道我是如何在第一次尝试时做到的 - 没有编译器错误,但这是我如何做到的:
// function prototype, the function body is not relevant here
string format(string str, vector<string> variables);
template <class T>
vector<string> paramsToString(vector<string> vec, T last) {
stringstream ss;
ss << last;
vec.push_back(ss.str());
return vec;
}
template <class T, class ... REST>
vector<string> paramsToString(vector<string> vec, T next, REST ... rest) {
stringstream ss;
ss << next;
vec.push_back(ss.str());
return paramsToString(vec, rest...);
}
template <class ... ARGS>
vector<string> paramsToString(ARGS ... args) {
return paramsToString(vector<string>(), args ...);
}
// ... some context
// ComplexType overrides the stream operator.
cout << format("an int: '{0}', and string: '{1}' and some other type: '{2}'",
paramsToString(10, "Hello World", ComplexType(10)));
它有效!即使有自定义类型。惊人!
谢谢你们的帮助!