I'm using boost::variant quite often in my projects. My colleagues now came up with the idea to pass around instances of specific boost::static_visitor<int> in order to customize the type of visitation. She had some code like the following:
#include <boost/variant.hpp>
#include <iostream>
typedef boost::variant<int, std::string> TVar;
struct Visitor1 : public boost::static_visitor<int> {
    template<typename T> 
    result_type operator()(const T&) {
        return 42;
    }
};
struct Visitor2 : public boost::static_visitor<int> {
    template<typename T>
    result_type operator()(const T&) {
        return 21;
    }
};
 int adder(const boost::static_visitor<int>& visitor, const TVar& visitable) {
     return visitable.apply_visitor(visitor) + 1;
 }
int main(int argc, char **args) {
    Visitor1 v1;
    Visitor2 v2;
    TVar x;
    std::cout << adder(v1, x) << std::endl;
    std::cout << adder(v2, x) << std::endl;
}
It looks perfectly sound to me, but it doesn't compile. My compiler says that expression will not yield a function that takes one 1 argument somewhere insider . 
What are we doing wrong?
There's an overload for apply_visitor that takes only the visitor. This returns a partially applied function object that suits your needs, I guess:
This overload returns a
Personally, I like to add an overload to the visitor object like this:
struct MyVisitor {
    typedef void result_type;
    template <typename... Ts>
    result_type operator()(boost::variant<Ts...> const& v) const {
         return boost::apply_visitor(*this, v);
    }
    // optionally repeat for non-const `v`
    // normal variant handling overloads
};
That way, you can simply use the visitor object as the function oject.
Firstly, you should mark your visitors' operator() overloads as const:
struct Visitor1 : public boost::static_visitor<int> {
    template<typename T> 
    result_type operator()(const T&) const {
        return 42;
    }
};
struct Visitor2 : public boost::static_visitor<int> {
    template<typename T>
    result_type operator()(const T&) const {
        return 21;
    }
};
Then, you need to change your adder to accept a template parameter instead of boost::static_visitor - it is your Visitor1 type that contains the operator() overload with the logic you desire. You need the "correct type" for the visitation to take place.
template <typename T>
int adder(const T& visitor, const TVar& visitable) {
    return visitable.apply_visitor(visitor) + 1;
}
live wandbox example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With