我想创建一个允许我在参数中使用<<
运算符的函数,并在其中使用相应的字符串流。
类似的东西:
/* This does not do what i want below */
void printStream(std::stringstream& ss) {
std::cout << ss.str();
}
/* Desired function usage */
printStream("The number is: " << 42 << ".");
我应该在函数声明中使用什么?
修改
根据Deduplicator建议,我尝试使用可变参数模板。出于我的目的,我决定创建一个模板,该模板获取参数列表并返回组合字符串。
这是代码:
template <typename First, typename... Rest> void getStringInner(std::stringstream& ss, const First& first, const Rest&... rest) {
ss << first;
getStringInner(ss, rest...);
}
template <typename First, typename... Rest> std::string getString(const First& first, const Rest&... rest) {
std::stringstream ss;
getStringInner(ss, first, rest...);
return ss.str();
}
不幸的是,Visual Studio给了我一个错误:
错误C2678:二进制&#39;&lt;&lt;&# :没有找到左手的操作员 类型&#39; std :: stringstream&#39;的操作数(或者没有可接受的 转换)main.cpp 42测试
ss << first;
中有错误的行为getStringInner
。
我做错了什么?
EDIT2:
我发现了错误。这是工作代码:
template <typename First> void getStringInner(std::stringstream& ss) {}
template <typename First> void getStringInner(std::stringstream& ss, const First& first) {
ss << first;
}
template <typename First, typename... Rest> void getStringInner(std::stringstream& ss, const First& first, const Rest&... rest) {
ss << first;
getStringInner(ss, rest...);
}
template <typename First, typename... Rest> std::string getString(const First& first, const Rest&... rest) {
std::stringstream ss;
getStringInner(ss, first, rest...);
return ss.str();
}
答案 0 :(得分:2)
不要这样做,它需要一个预处理程序 - 黑客。
只需使用可变参数模板和逗号代替左移:
template<class... X> void printStream(X&&... x) {
std::stringstream ss;
((void)0, (void)(ss<<x), ...);
std::cout << ss.rdbuf();
}
答案 1 :(得分:1)
您在C ++中寻找的内容很难,因为传递给函数的表达式将独立计算;例如,如果a
和b
是整数,则无法编写函数或模板foo
以便
foo(a << b);
做一些不同于调用foo
传递a
移位b
(编译器将单独查看a << b
,从而生成一个bithift操作。)
你可以做的是使用预处理器,即通过编写预处理器宏,foo
可以生成你正在寻找的东西。
#define foo(x) \
do{ \
std::ostream s_; \
s_ << x; \
std::cout << s_.str(); \
} while(0)
这项工作通过利用通常被认为是C预处理器的限制,即它通过文本替换来工作。换句话说,编译器将被要求编译s_ << a << b
。
答案 2 :(得分:1)
您可以使用宏:
#define printStream(arg) std::cout << arg
因此,当您编写printStream("The number is: " << 42 << ".");
时,它将扩展为:
std::cout << "The number is: " << 42 << ".";
你想做什么。
答案 3 :(得分:0)
如果不更改通话网站,您将无法执行此操作。 "The number is: " << 42
只是一个带有char[]
和int
操作数的移位操作,不管表达式的结果是否应该传递给其他函数。
如果您愿意稍微更改调用,则可以使用重载operator<<
的代理类,并将工作委派给std::ostringstream
。这是一个基本的例子:
#include <iostream>
#include <sstream>
#include <string>
class Printer {
private:
std::ostringstream oss;
public:
Printer() {
}
std::string string() const {
return oss.str();
}
template <class T>
Printer& operator<<(T const& t) {
oss << t;
return *this;
}
};
void printStream(Printer const& printer) {
std::cout << printer.string();
}
int main() {
printStream(Printer() << "The number is: " << 42 << ".");
}
答案 4 :(得分:0)
我想到的是创建自己的字符串类,例如Cl_CharArray
,并添加运算符&lt;&lt;这将从左右两个字符串中生成一个新的Cl_CharArray
。
可能需要使用模板。这个任务很有趣,我也会在某个时候做,然后回到这里。然后每个类都需要一个函数来使它成为一个字符串(char数组)。我认为至少有一方(任何一个操作员的左侧或右侧)必须是一个类,所以它应该没问题(有一个数字)。