1

suppose that I have such a variant definition:

typedef boost::variant <
v1,
v2,
v3,
...
vn
> v;

and I need to write a visitor class with visitor functions for each v1 to vn like this:

class myvisitor : public boost::static_visitor<bool> {
  bool operator()(v1) {}
  bool operator()(v2) {}
   ...
  bool operator()(vn) {}
}

So if all such functions are the same except the one for v1, then I would like to only define

 bool operator()(v1) {}

while leave all others to some default form to avoid writing lots of useless and duplicated code.

So if this is possible? or can the boost developer do this on his next version?

shengyushen
  • 289
  • 3
  • 13

1 Answers1

4

Just make the default "case" an open template member operator():

Live On Coliru

#include <boost/variant.hpp>
#include <iostream>

struct MyStruct {
    int a, b, c;
};

using V = boost::variant<int, MyStruct, std::string, double>;

struct MyVisitor : boost::static_visitor<void> {
    void operator()(int) const                 { std::cout << __PRETTY_FUNCTION__ << "\n"; } 
    void operator()(std::string const &) const { std::cout << __PRETTY_FUNCTION__ << "\n"; } 

    // the default case:
    template <typename T> void operator()(T const &) const {
        std::cout << "FALLBACK: " << __PRETTY_FUNCTION__ << "\n"; 
    } 
};

int main() {
    V v;

    for (auto v : { V(42), V(3.14), V("hello world"), V( MyStruct{1,2,3} ) })
        boost::apply_visitor(MyVisitor(), v);
}

Output:

void MyVisitor::operator()(int) const
FALLBACK: void MyVisitor::operator()(const T&) const [with T = double]
void MyVisitor::operator()(const string&) const
FALLBACK: void MyVisitor::operator()(const T&) const [with T = MyStruct]
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Welcome to c++ :) Also, in case you're interested, I live-stream most of my answers: [recorded](https://www.livecoding.tv/video/thread-cancellationvariant-visitor-fallback/) – sehe Jan 13 '16 at 10:06
  • I suddenly realize that this code style open up a totally new possbility for me, I used to program in ocaml and it have a similar notation "_" that match everything except previous specified ones. In c++ I am forced to write awk scripts to generate all those useless cases. This release me from such labor. – shengyushen Jan 13 '16 at 10:14
  • You might be interested in a devious little idiom that I sometimes use to define visitors on the spot: http://stackoverflow.com/a/27138091/85371 (look for `make_visitor`) – sehe Jan 13 '16 at 10:21
  • A further question is: can I specify a common behavior for a set of types? – shengyushen Jan 13 '16 at 14:34
  • Yes. Use regular overloading and template metaprogramming techniques (enable_if, tag-dispatch, overload resolution) – sehe Jan 13 '16 at 15:28
  • Demo of [sfinae-based template resolution](http://coliru.stacked-crooked.com/a/b93a46f166b5c3fa). Alternative using [tag dispatch}(http://coliru.stacked-crooked.com/a/7e31b9b01586d376) – sehe Jan 13 '16 at 19:15