Учитывая следующее (сведено к основам):
#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;
}
... однако эта вторая версия не работает, и я озадачен, почему бы и нет. Ошибка компилятора (clang ++ 6.0.0 в Linux):
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 с той же проблемой, за исключением еще большего количества ошибок. Может кто-нибудь объяснить мне, что я делаю не так?