在函数参数中使用 << 运算符
Use << operator inside function arguments
我想创建一个函数,允许我在参数中使用 <<
运算符,并在其中使用相应的字符串流。
类似于:
/* 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 的建议,我正在尝试使用可变参数模板。出于我的目的,我决定创建一个模板,该模板采用参数列表和 returns 组合字符串。
这是代码:
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给我一个错误:
error C2678: binary '<<' : no operator found which takes a left-hand
operand of type 'std::stringstream' (or there is no acceptable
conversion) main.cpp 42 Test
错误的行是 getStringInner
中的 ss << first;
。
我做错了什么?
编辑2:
我发现了错误。这是工作代码:
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();
}
你要找的东西在 C++ 中很难,因为传递给函数的表达式将被独立计算;例如,如果 a
和 b
是整数,则无法编写函数或模板 foo
以便
foo(a << b);
做一些不同于调用 foo
传递 a
移位 b
的事情(编译器将单独查看 a << b
从而生成位移操作)。
您可以做的是使用预处理器,即可以 foo
通过编写预处理器宏来生成您正在寻找的内容。
#define foo(x) \
do{ \
std::ostream s_; \
s_ << x; \
std::cout << s_.str(); \
} while(0)
这项工作利用了通常被认为是 C 预处理器的限制,即它通过文本替换工作。换句话说,编译器将被要求编译 s_ << a << b
.
您可以使用宏:
#define printStream(arg) std::cout << arg
因此,当您写 printStream("The number is: " << 42 << ".");
时,它将扩展为:
std::cout << "The number is: " << 42 << ".";
哪个是你想要的。
不要那样做,它需要预处理器破解。
只需使用可变参数模板和逗号而不是左移:
template<class... X> void printStream(X&&... x) {
std::stringstream ss;
((void)0, (void)(ss<<x), ...);
std::cout << ss.rdbuf();
}
如果不更改调用站点,您将无法执行此操作。 "The number is: " << 42
只是一个带有 char[]
和一个 int
操作数的移位操作,而不管表达式的结果随后应该传递给其他函数的事实。
如果您愿意稍微更改调用,则可以使用代理 class 重载 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 << ".");
}
我想到的是创建您自己的字符串 class,例如 Cl_CharArray
,并向其添加运算符<<,这将从左边的字符串中创建一个新的 Cl_CharArray
和对了。
可能需要使用模板。这个任务很有趣,我也会在return这里做的。每个 class 然后需要一个函数来将它变成一个字符串(字符数组)。我认为至少一侧(任何运算符的左侧或右侧)必须是 class,所以应该没问题(有一个数字)。
我想创建一个函数,允许我在参数中使用 <<
运算符,并在其中使用相应的字符串流。
类似于:
/* 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 的建议,我正在尝试使用可变参数模板。出于我的目的,我决定创建一个模板,该模板采用参数列表和 returns 组合字符串。
这是代码:
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给我一个错误:
error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'std::stringstream' (or there is no acceptable conversion) main.cpp 42 Test
错误的行是 getStringInner
中的 ss << first;
。
我做错了什么?
编辑2:
我发现了错误。这是工作代码:
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();
}
你要找的东西在 C++ 中很难,因为传递给函数的表达式将被独立计算;例如,如果 a
和 b
是整数,则无法编写函数或模板 foo
以便
foo(a << b);
做一些不同于调用 foo
传递 a
移位 b
的事情(编译器将单独查看 a << b
从而生成位移操作)。
您可以做的是使用预处理器,即可以 foo
通过编写预处理器宏来生成您正在寻找的内容。
#define foo(x) \
do{ \
std::ostream s_; \
s_ << x; \
std::cout << s_.str(); \
} while(0)
这项工作利用了通常被认为是 C 预处理器的限制,即它通过文本替换工作。换句话说,编译器将被要求编译 s_ << a << b
.
您可以使用宏:
#define printStream(arg) std::cout << arg
因此,当您写 printStream("The number is: " << 42 << ".");
时,它将扩展为:
std::cout << "The number is: " << 42 << ".";
哪个是你想要的。
不要那样做,它需要预处理器破解。
只需使用可变参数模板和逗号而不是左移:
template<class... X> void printStream(X&&... x) {
std::stringstream ss;
((void)0, (void)(ss<<x), ...);
std::cout << ss.rdbuf();
}
如果不更改调用站点,您将无法执行此操作。 "The number is: " << 42
只是一个带有 char[]
和一个 int
操作数的移位操作,而不管表达式的结果随后应该传递给其他函数的事实。
如果您愿意稍微更改调用,则可以使用代理 class 重载 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 << ".");
}
我想到的是创建您自己的字符串 class,例如 Cl_CharArray
,并向其添加运算符<<,这将从左边的字符串中创建一个新的 Cl_CharArray
和对了。
可能需要使用模板。这个任务很有趣,我也会在return这里做的。每个 class 然后需要一个函数来将它变成一个字符串(字符数组)。我认为至少一侧(任何运算符的左侧或右侧)必须是 class,所以应该没问题(有一个数字)。