给出以下内容(精简为基本内容):
#include <memory>
#include <ostream>
#include <string>
#include <variant>
struct Cell;
using Expression =
std::variant<std::string, std::shared_ptr<Cell>, std::nullptr_t>;
struct Cell {
explicit Cell(Expression car, Expression cdr) : car_{car}, cdr_{cdr} {
}
Expression car_;
Expression cdr_;
};
我想为表达式创建一个输出迭代器。我的第一次尝试是这样的:
std::ostream& operator<<(std::ostream& out, const Expression& exp) {
switch (exp.index()) {
case 0:
out << std::get<0>(exp);
break;
case 1: {
auto cell = std::get<1>(exp);
out << "( " << cell->car_ << " . " << cell->cdr_ << " )";
}
break;
case 2:
out << "()";
break;
}
return out;
}
这行得通,但我认为我可以做得更好(可读性更高,更易维护等)。
struct ExpressionOutputVisitor {
std::ostream& out_;
ExpressionOutputVisitor(std::ostream& out) : out_{out} {
}
void operator()(std::string& arg) const {
out_ << arg << '\n';
}
void operator()(std::shared_ptr<Cell>& arg) const {
out_ << "( " << arg->car_ << " . " << arg->cdr_ << " )"; // error at arg->car_
}
void operator()(std::nullptr_t) const {
out << "()";
}
};
std::ostream& operator<<(std::ostream& out, Expression& exp) {
std::visit(ExpressionOutputVisitor{out}, exp);
return out;
}
...但是第二个版本不起作用,我为为什么不感到困惑。来自编译器的错误(在Linux上为clang ++ 6.0.0)是:
error: invalid operands to binary expression
('basic_ostream<char, std::char_traits<char> >' and 'Expression' (aka
'variant<basic_string<char>, shared_ptr<Cell>, nullptr_t>'))
out_ << "(" << arg->car_ << " " << arg->cdr_ << ")";
~~~~~~~~~~~ ^ ~~~~~~~~~
接着是通常的几页喷溅物。我还尝试了g ++ 7.3.0的相同问题,但输出的错误更多。谁能向我解释我在做什么错?
答案 0 :(得分:0)
第一个版本是自递归的。由于该功能本身是已知的,因此可以正常工作。
第二个版本具有多个相互递归函数。在定义之前,您需要使用的前向声明。
添加行
std::ostream& operator<<(std::ostream& out, Expression& exp);
在struct ExpressionOutputVisitor { ... };
之前
失败与声明点有关,与std::visit
或std::variant
没有关系。