0

I get a compiler regarding apply_visitor within the current operator. I tested all the apply_visitor outside of that method and it works perfectly fine. Just when trying to use it within that method it runs into a bunch of issues.

The error message is confusing me.

So, Why is trying to use apply_visitor for a different visitor is running into problems within the current visitor?

Here the Snippet of the code that have give me the errors:

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])))) {
            }
        }
    }
  }
};

At first, I thought maybe

vector<ObjectE> list = v[2]; 

was the issue. So I created a visitor who will return a vector.

However, it seem that most of the errors are :

 error: no match for call to '(const ReturnVal) (std::__cxx11::basic_string<char>&)'

which I'm not sure what it mean.

Can someone explain to me what the issue is?

sehe
  • 374,641
  • 47
  • 450
  • 633
Leruce
  • 187
  • 1
  • 8
  • 1
    Please provide a [mcve]. This means deleting every line and expression that does not prevent the compile error. But including every line required for the build error. We should be abke to copy paste posted code to repo the error, and there should be *less* code than you posted above. – Yakk - Adam Nevraumont Dec 14 '17 at 12:12
  • Your code is incomplete; in particular, it seems to be missing a `main()` function and at least one `#include`. Please [edit] your code so it's a [mcve] of your problem, then we can try to reproduce and solve it. You should also read [ask]. – Toby Speight Dec 14 '17 at 16:33

1 Answers1

1

Hah. Look back at my older answer to you: enter image description here

Calls like

boost::apply_visitor(ReturnType(), tail)

call pass the visitor as a temporary, so it can only bind to a const&. This means that all call-operator overloads required must be const-qualified, because otherwise they won't apply, as you're being told:

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);
}

Compiles. Ucommenting the line commented with // COMPILE RROR gives:

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);

Skip the required from chain, scan for error: first and then notice the note: that says:

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

It's pretty clear once you look for it: passing 'const NotWorkingWithTemporaries*' as 'this' argument discards qualifiers. The only thing you need to know is const is known as a qualifier¹.


¹ const, volatile and rvalue-ref (&&)

OTHER REMARKS

Trying to get the rest of your non-self-contained question code to compile reveals similar issues with the std::string overloads:

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

(note std::string const& instead of std::string&).

Other than that... it look as though you're abusing vectors to represent Expressions. Why not make it strong typed and a lot less error-prone?

See e.g. Building a Custom Expression Tree in Spirit:Qi (Without Utree or Boost::Variant)

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Added "OTHER REMARKS" - ironically this matches more closely the message you showed in the question. (Off-Topic: Are you using MSVC++? Because that compiler is non-conformant and might allow the use of the temporaries in `apply_visitor` even without proper const-qualification. I haven't checked) – sehe Dec 14 '17 at 14:02
  • For some reason you even hard-coded an infinite loop in the vector-overload. Really. Sit back, tell us what you're trying to represent (I have the feeling you're doing some kind of Lisp-style programming language, but you fail to properly parse to an AST and then scatter all your semantics throughout some code, meaning everything will just break spectacularly on unexpected input... Empty vector? [BOOM](https://en.wikipedia.org/wiki/Undefined_behavior). No trailing `"nil"` literal in a cons? [BOOM](https://en.wikipedia.org/wiki/Infinite_loop). – sehe Dec 14 '17 at 14:25
  • I finally managed to "accidentally" find an input that at least doesn't crash and burn, proving you can make that "thing" compile [Live On Coliru](http://coliru.stacked-crooked.com/a/a4acd6e444b49521) with the hints from my answer. It's still far removed from good code. – sehe Dec 14 '17 at 14:30