如何在 boost::variant 中的另一个 static_visitor 中解析 apply_visitor? [关闭]
Posted
技术标签:
【中文标题】如何在 boost::variant 中的另一个 static_visitor 中解析 apply_visitor? [关闭]【英文标题】:How to resolve an apply_visitor within another static_visitor in boost::variant? [closed] 【发布时间】:2017-12-14 11:59:44 【问题描述】:我在当前运算符中获得了一个关于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>&)'
我不确定这是什么意思。
谁能给我解释一下是什么问题?
【问题讨论】:
请提供minimal reproducible example。这意味着删除不会阻止编译错误的每一行和表达式。但包括构建错误所需的每一行。我们应该可以复制粘贴发布的代码来解决错误,并且应该比您上面发布的代码少。 您的代码不完整;特别是,它似乎缺少一个main()
函数和至少一个#include
。请edit您的代码,这是您的问题的minimal reproducible example,然后我们可以尝试重现并解决它。您还应该阅读How to Ask。
【参考方案1】:
哈。回头看看我的older answer to you:
喜欢的电话
boost::apply_visitor(ReturnType(), tail)
将访问者作为临时调用传递,因此它只能绑定到const&
。这意味着所需的所有调用运算符重载必须为const
-qualified,否则它们将不适用,正如您被告知的那样:
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);
编译。 Ucommenting 用// 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
和右值引用 (&&
)
其他说明
尝试编译其余的非独立问题代码会发现与 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)
【讨论】:
添加了“其他评论” - 具有讽刺意味的是,这更接近您在问题中显示的信息。 (题外话:你在使用 MSVC++ 吗?因为那个编译器不符合标准,即使没有适当的 const 限定,也可能允许使用apply_visitor
中的临时变量。我没有检查)
出于某种原因,您甚至在矢量重载中硬编码了一个无限循环。真的。坐下来,告诉我们你想表达什么(我感觉你在做某种 Lisp 风格的编程语言,但是你没有正确解析为 AST,然后将所有语义分散在一些代码中,这意味着一切都会因意外输入而崩溃...空向量?BOOM。没有尾随 "nil"
字面量?BOOM。
我终于设法“意外”找到了一个至少不会崩溃和烧毁的输入,证明您可以使用我的回答中的提示使那个“东西”编译Live On Coliru。它距离好的代码还很远。以上是关于如何在 boost::variant 中的另一个 static_visitor 中解析 apply_visitor? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
Boost::Variant 和其中的 function_types:如何将函数放入 Boost::variant?
如何返回由 boost::variant 返回类型中包含的类型的子集组成的 boost::variant