我在当前运算符中得到了关于apply_visitor
的编译器。
我测试了该方法之外的所有apply_visitor
,它完全正常。就在尝试在该方法中使用它时,它会遇到一堆问题。
错误信息令我感到困惑。
那么,为什么尝试将apply_visitor
用于其他访问者会遇到当前访问者中的问题?
这里给出了错误的代码片段:
typedef boost::make_recursive_variant<string, int, vector<boost::recursive_variant_ > >::type ObjectE;
class ReturnType : public boost::static_visitor<string> {
public:
string operator()(string &s) { return "string"; }
string operator()(int i) {return "int";}
string operator()(std::vector<ObjectE> const &v) {return "vector";}
};
class ReturnVal : public boost::static_visitor<string> {
public:
string operator()(string &s) { return s; }
string operator()(int i) {return to_string(i);}
string operator()(std::vector<ObjectE> const &v) {return "vector";}
};
class ReturnV : public boost::static_visitor<vector<ObjectE>> {
public:
vector<ObjectE> operator()(string &s){ return {};}
vector<ObjectE> operator()(int i) {return {};}
vector<ObjectE> operator()(vector<ObjectE> const &v) {return v;}
};
struct create_Str {
using result_type = void;
std::ostream & out;
template <typename T> void call(T const &v) { return operator()(v);}
template <typename... Ts> void operator()(boost::variant<Ts...> const &v) {
return boost::apply_visitor(*this, v);
}
void operator()(int i) { out << i; }
void operator()(std::string const &s) { out << s; }
template <typename... Ts> void operator()(std::vector<Ts...> const &v) {
string name = boost::apply_visitor(ReturnVal(), v[0]);
if (v.size() == 3 && isOp(name)) {
}
else if (v.size() == 3 && isListCons(name)) {
call(v[1]);
ObjectE tail = v[2];
for (;;) {
if ("[]" == boost::get<string>(tail) || "nil" == boost::get<string>(tail)) {
break;
}
if ( !(boost::apply_visitor(ReturnType(), tail) == "vector")) {
}
vector<ObjectE> list = boost::apply_visitor(ReturnV(), v[2]);;
if (!(list.size() == 3 && isListCons(boost::apply_visitor(ReturnVal(), list[0])))) {
}
}
}
}
};
起初,我想也许
vector<ObjectE> list = v[2];
是个问题。所以我创建了一个返回向量的访问者。
然而,似乎大多数错误都是:
error: no match for call to '(const ReturnVal) (std::__cxx11::basic_string<char>&)'
我不确定它是什么意思。
有人可以向我解释问题是什么吗?
答案 0 :(得分:1)
哈。回顾我的older answer to you:
调用
boost::apply_visitor(ReturnType(), tail)
调用将访问者作为临时文件传递,因此它只能绑定到const&
。这意味着所有呼叫操作员超载都必须必须为const
- 否则,因为否则它们将无法应用,因为您被告知:
<强> Live On Coliru 强>
#include <boost/variant.hpp>
struct Ok : boost::static_visitor<> {
void operator()(std::string const&) const {}
void operator()(int) const {}
};
struct NotWorkingWithTemporaries : boost::static_visitor<> {
void operator()(std::string const&) const {}
void operator()(int) {} // whoops, missing const-qualifier
};
int main() {
boost::variant<std::string, int> v;
boost::apply_visitor(Ok{}, v);
//boost::apply_visitor(NotWorkingWithTemporaries{}, v); // COMPILE ERROR
// however, this works:
NotWorkingWithTemporaries not_a_temporary;
boost::apply_visitor(not_a_temporary, v);
}
编译。用注释// COMPILE RROR
的行注释:
<强> Live On Coliru 强>
In file included from /usr/local/include/boost/variant.hpp:17:0,
from main.cpp:1:
/usr/local/include/boost/variant/variant.hpp: In instantiation of 'boo...
/usr/local/include/boost/variant/detail/visitation_impl.hpp:114:9: r...
/usr/local/include/boost/variant/detail/visitation_impl.hpp:154:41: ...
/usr/local/include/boost/variant/detail/visitation_impl.hpp:238:5: r...
/usr/local/include/boost/variant/variant.hpp:2390:48: required from ...
/usr/local/include/boost/variant/variant.hpp:2404:43: required from ...
/usr/local/include/boost/variant/variant.hpp:2429:52: required from ...
/usr/local/include/boost/variant/detail/apply_visitor_unary.hpp:84:43:...
main.cpp:17:56: required from here
/usr/local/include/boost/variant/variant.hpp:1046:24: error: no match ...
return visitor_(operand);
~~~~~~~~^~~~~~~~~
main.cpp:9:10: note: candidate: void NotWorkingWithTemporaries::operat...
void operator()(std::string const&) const {}
^~~~~~~~
main.cpp:9:10: note: no known conversion for argument 1 from 'int' t...
main.cpp:10:10: note: candidate: void NotWorkingWithTemporaries::opera...
void operator()(int) {} // whoops, missing const-qualifier
^~~~~~~~
main.cpp:10:10: note: passing 'const NotWorkingWithTemporaries*' as ...
In file included from /usr/local/include/boost/variant.hpp:17:0,
from main.cpp:1:
/usr/local/include/boost/variant/variant.hpp:1046:32: error: return-st...
return visitor_(operand);
跳过 required from
链,首先扫描 error:
,然后注意note:
那说:
main.cpp:10:10: note: candidate: void NotWorkingWithTemporaries::operator()(int) <near match>
void operator()(int) {} // whoops, missing const-qualifier
^~~~~~~~
main.cpp:10:10: note: passing 'const NotWorkingWithTemporaries*' as 'this' argument discards qualifiers
一旦你找到它就很清楚了: passing 'const NotWorkingWithTemporaries*' as 'this' argument discards qualifiers
。您唯一需要知道的是const
被称为限定符¹。
¹const
,volatile
和rvalue-ref(&&
)
尝试将其余的非自包含问题代码编译为std::string
重载的类似问题:
std::string operator()(std::string const & /*s*/) const { return "std::string"; }
(注意std::string const&
而不是std::string&
)。
除此之外......看起来好像你在滥用向量来表示表达式。为什么不把它打造成强类型而且更不容易出错?
参见例如Building a Custom Expression Tree in Spirit:Qi (Without Utree or Boost::Variant)