如何解决boost :: variant中另一个static_visitor中的apply_visitor?

时间:2017-12-14 11:59:45

标签: c++ boost boost-variant

我在当前运算符中得到了关于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>&)'

我不确定它是什么意思。

有人可以向我解释问题是什么吗?

1 个答案:

答案 0 :(得分:1)

哈。回顾我的older answer to youenter image description here

调用

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被称为限定符¹。

¹constvolatile和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)