没有找到Boost.Spirit前pression重载输出操作符 [英] Overloaded output operator not found for Boost.Spirit expression
问题描述
这是在 这个Q&功放的后续; A 。我现在有一个命名空间AST几个数据结构
,细分了两个子命名空间(代数
和数字对应于两种不同格式的语法识别
)。
This is a follow-up on this Q&A. I now have several data structures in a namespace ast
, subdivided over two sub-namespaces (algebraic
and numeric
) that correspond to the two different formats that the grammar recognizes.
namespace ast {
namespace algebraic {
struct occupance
{
char pc;
char col;
int row;
};
using pieces = std::vector<occupance>;
struct placement
{
char c;
boost::optional<pieces> p;
};
}
namespace numeric {
struct occupance
{
char pc;
int sq;
};
struct range
{
occupance oc;
int sq;
};
using pieces = std::vector<boost::variant<range, occupance>>;
struct placement
{
char c;
boost::optional<pieces> p;
};
}
struct fen
{
char c;
std::vector<boost::variant<numeric::placement, algebraic::placement>> p;
};
}
工作解析器的 <大骨节病> 住在Coliru 骨节病>
麻烦的开始,当我尝试定义流运营商的多种类型。与普通的运营商的LT;&LT;
走矢量&lt; T&GT;
在同一个命名空间中的各种 AST
结构(如链接的Q&安培; A),一切都很好。但是,一旦我有两个子命名空间代数
和数字
,并在这些名称空间中定义的各种操作:
The trouble starts when I try to define streaming operators for the various types. With the generic operator<<
taking a vector<T>
in the same namespace as the various ast
structs (as in the linked Q&A), all is fine. But once I have two sub-namespaces algebraic
and numeric
and define the various operators in these namespaces:
namespace ast {
template <typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> const& v)
{
os << "{";
for (auto const& el : v)
os << el << " ";
return os << "}";
}
namespace algebraic {
std::ostream& operator<<(std::ostream& os, occupance const& oc)
{
return os << oc.pc << oc.col << oc.row;
}
std::ostream& operator<<(std::ostream& os, placement const& p)
{
return os << p.c << " " << p.p;
}
} // algebriac
namespace numeric {
std::ostream& operator<<(std::ostream& os, occupance const& oc)
{
return os << oc.pc << oc.sq;
}
std::ostream& operator<<(std::ostream& os, range const& r)
{
for (auto sq = r.oc.sq; sq <= r.sq; ++sq)
os << r.oc.pc << sq << " ";
return os;
}
std::ostream& operator<<(std::ostream& os, placement const& p)
{
return os << p.c << " " << p.p;
}
} // numeric
} // ast
<大骨节病> 住在Coliru 骨节病> 相应的运营商都不再被发现。
Live On Coliru the appropriate operators are no longer being found.
In file included from main.cpp:4:
/usr/local/include/boost/optional/optional_io.hpp:47:21: error: invalid operands to binary expression ('basic_ostream<char, std::__1::char_traits<char> >' and 'const std::__1::vector<ast::algebraic::occupance, std::__1::allocator<ast::algebraic::occupance> >')
else out << ' ' << *v ;
~~~~~~~~~~ ^ ~~
main.cpp:79:37: note: in instantiation of function template specialization 'boost::operator<<<char, std::__1::char_traits<char>, std::__1::vector<ast::algebraic::occupance, std::__1::allocator<ast::algebraic::occupance> > >' requested here
return os << p.c << " " << p.p;
问:如何界定的各种流媒体运营商正确打印匹配的AST
Question: how to define the various streaming operators to properly print the matched AST?
推荐答案
它运行的设施,工厂ADL。 (<一href=\"https://stackoverflow.com/questions/8111677/what-is-argument-dependent-lookup-aka-adl-or-koenig-lookup/8111750#8111750\">What是&QUOT;参数依赖性查找&QUOT;(又名ADL,或QUOT; Koenig查找&QUOT;)?)
It's run-of-the-mill ADL. (What is "Argument-Dependent Lookup" (aka ADL, or "Koenig Lookup")?)
无论是复制运营商的LT;&LT;
每个子名字空间或使用ADL钩标签
Either duplicate the operator<<
for each subnamespace or use an ADL hook "tag".
<大骨节病> 住在Coliru 骨节病>
请注意在 adl_hook
类型和用途:
<大骨节病> 住在Coliru 骨节病>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/optional/optional_io.hpp>
#include <boost/optional.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <vector>
namespace x3 = boost::spirit::x3;
namespace ast {
struct adl_hook;
template <typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> const& v) {
os << "{"; for (auto const& el : v) os << el << " "; return os << "}";
}
namespace algebraic {
template <typename tag = adl_hook>
struct occupance_t
{
char pc;
char col;
int row;
};
using occupance = occupance_t<>;
using pieces = std::vector<occupance>;
template <typename tag = adl_hook>
struct placement_t
{
char c;
boost::optional<pieces> p;
};
using placement = placement_t<>;
}
namespace numeric {
template <typename tag = adl_hook>
struct occupance_t
{
char pc;
int sq;
};
using occupance = occupance_t<>;
struct range
{
occupance oc;
int sq;
};
using piece = boost::variant<range, occupance>;
using pieces = std::vector<piece>;
template <typename tag = adl_hook>
struct placement_t
{
char c;
boost::optional<pieces> p;
};
using placement = placement_t<>;
}
struct fen
{
char c;
using placement = boost::variant<numeric::placement, algebraic::placement>;
std::vector<placement> p;
};
namespace algebraic {
std::ostream& operator<<(std::ostream& os, occupance const& oc)
{
return os << oc.pc << oc.col << oc.row;
}
std::ostream& operator<<(std::ostream& os, placement const& p)
{
return os << p.c << " " << p.p;
}
} // algebriac
namespace numeric {
std::ostream& operator<<(std::ostream& os, occupance const& oc)
{
return os << oc.pc << oc.sq;
}
std::ostream& operator<<(std::ostream& os, range const& r)
{
for (auto sq = r.oc.sq; sq <= r.sq; ++sq)
os << r.oc.pc << sq << " ";
return os;
}
std::ostream& operator<<(std::ostream& os, placement const& p)
{
return os << p.c << " " << p.p;
}
} // numeric
} // ast
BOOST_FUSION_ADAPT_STRUCT(ast::algebraic::occupance, pc, col, row)
BOOST_FUSION_ADAPT_STRUCT(ast::algebraic::placement, c, p )
BOOST_FUSION_ADAPT_STRUCT(ast::numeric::occupance, pc, sq)
BOOST_FUSION_ADAPT_STRUCT(ast::numeric::range, oc, sq)
BOOST_FUSION_ADAPT_STRUCT(ast::numeric::placement, c, p )
BOOST_FUSION_ADAPT_STRUCT(ast::fen, c, p )
namespace grammar {
auto const colon = x3::lit(':');
auto const comma = x3::lit(',');
auto const dash = x3::lit('-');
auto const dot = x3::lit('.');
template<typename T>
auto as_rule = [](auto p) { return x3::rule<struct _, T>{} = x3::as_parser(p); };
auto const piece_type = x3::char_('K') | x3::attr('M');
auto const color = x3::char_("BW");
namespace algebraic {
auto const square = x3::lower >> x3::uint_;
auto const occupance = as_rule<ast::algebraic::occupance> ( piece_type >> square );
auto const pieces = as_rule<ast::algebraic::pieces> ( occupance % comma );
auto const placement = as_rule<ast::algebraic::placement> ( colon >> color >> -pieces );
} // algebraic
namespace numeric {
auto const square = x3::uint_;
auto const occupance = as_rule<ast::numeric::occupance> ( piece_type >> square );
auto const range = as_rule<ast::numeric::range> ( occupance >> dash >> square );
auto const pieces = as_rule<ast::numeric::pieces> ( (range | occupance) % comma );
auto const placement = as_rule<ast::numeric::placement> ( colon >> color >> -pieces );
} // numeric
auto const fen = as_rule<ast::fen> ( color >> (x3::repeat(2)[numeric::placement] | x3::repeat(2)[algebraic::placement]) >> -dot );
} // grammar
int main() {
for (std::string const t : {
"W:Wa1,c1,e1,g1,b2,d2,f2,h2,a3,c3,e3,g3:Bb8,d8,f8,h8,a7,c7,e7,g7,b6,d6,f6,h6",
"W:BKa1,Ka3:WKb8,Kd8",
"B:W18,24,27,28,K10,K15:B12,16,20,K22,K25,K29",
"B:W18,19,21,23,24,26,29,30,31,32:B1,2,3,4,6,7,9,10,11,12",
"W:B1-20:W31-50", // initial position
"W:B:W", // empty board
"W:B1:W", // only black pieces
"W:B:W50" // only white pieces
}) {
auto b = t.begin(), e = t.end();
ast::fen data;
bool ok = phrase_parse(b, e, grammar::fen, x3::space, data);
std::cout << t << "\n";
if (ok) {
std::cout << "\t Parsed: \n" << boost::fusion::as_vector(data) << "\n";
} else {
std::cout << "Parse failed:\n";
std::cout << "\t on input: " << t << "\n";
}
if (b != e)
std::cout << "\t Remaining unparsed: '" << std::string(b, e) << '\n';
}
}
这篇关于没有找到Boost.Spirit前pression重载输出操作符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!