如何在 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&amp;。这意味着所需的所有调用运算符重载必须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 被称为限定符¹。


¹constvolatile 和右值引用 (&amp;&amp;)

其他说明

尝试编译其余的非独立问题代码会发现与 std::string 重载类似的问题:

std::string operator()(std::string const & /*s*/) const  return "std::string"; 

(注意 std::string const&amp; 而不是 std::string&amp;)。

除此之外...看起来您正在滥用向量来表示表达式。为什么不让它成为强类型并且更不容易出错呢?

参见例如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

boost::variant 如何存储引用?

使用 boost::mpl 获取 boost::variant 的类型索引

如何将项目从 boost::variant 移动到多地图?

使用 boost::variant 库制作地图。如何将事物存储和显示为正确的类型?