1

The code below uses a boost variant of an std::map which contains int/MyVariant pairs. I am able to initialize my map correctly where the first element contains the 33/A pair and the second contains 44/B pair. A and B each have a function that I would like to be able to call after retrieving respectively their initialized map element:

#include "stdafx.h"
#include "boost/variant/variant.hpp"
#include "boost/variant/get.hpp"
#include "boost/variant/apply_visitor.hpp"
#include <map>

struct A { void Fa() {} };
struct B { void Fb() {} };

typedef boost::variant< A, B > MyVariants;
typedef std::map< const int, MyVariants > MyVariantsMap;
typedef std::pair< const int, MyVariants > MyVariantsMapPair;

struct H
{
  H( std::initializer_list< MyVariantsMapPair > initialize_list ) : myVariantsMap( initialize_list ) {}

  MyVariantsMap myVariantsMap;
};

int main()
{
  H h { { 33, A {} }, { 44, B { } } };

  auto myAVariant = h.myVariantsMap[ 33 ];
  auto myBVariant = h.myVariantsMap[ 44 ];

  A a;
  a.Fa(); // ok

  // but how do I call Fa() using myAVariant?
   //myAVariant.Fa(); // not the right syntax

  return 0;
}

What would be the correct syntax for doing that?

rtischer8277
  • 496
  • 6
  • 27
  • 1
    have you tried `boost::get(myAVariant).Fa()`? – W.F. Jul 08 '16 at 20:04
  • Yes. The problem with that is, variant information has to be applied twice. Once when inserting the map pair and once when it is retrieved. Should be IMO only once. – rtischer8277 Jul 08 '16 at 20:36
  • 1
    From the compiler point of view by using variant you erase the information what is the variable real type. C++ is still strongly typed language and as such the information should be at some point provided back... – W.F. Jul 08 '16 at 20:42
  • Maybe boost variant isn't strongly typed, but the proposed c++17 std::variant, at least, is billed as being strongly typed. – rtischer8277 Jul 08 '16 at 20:46
  • I think what you would like the variant work demands c++ having deduction of the template function result... And unfortunately I don't think c++17 will introduce it... – W.F. Jul 08 '16 at 20:53
  • Here is a link to Axel Haumann's paper: [c++17 Variant](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0088r2.html) – rtischer8277 Jul 08 '16 at 21:00
  • My usage expectation for std::variant is that it would be able to automatically specialize because of its inherent typing information which would let the syntax for the code above be: get<>(myAVariant).Fa(); – rtischer8277 Jul 08 '16 at 21:05
  • But in myAVariant at compile time compiler does not get the information which type should get return so at best the compiler should deduce it and it would be hard by using only inner method invocation... – W.F. Jul 08 '16 at 21:08
  • But better deduction seems to be the way c++17 is heading. Fx, template< auto and template – rtischer8277 Jul 08 '16 at 21:09
  • As far as I know in c++17 the type parameter of templated type can be deduced by using initializer... No deduction of templated function result for now... – W.F. Jul 08 '16 at 21:13

1 Answers1

3

The boost::variant way to do this is using a visitor:

#include <boost/variant/variant.hpp>
#include <map>
#include <iostream>
struct A { void Fa() {std::cout << "A" << std::endl;} };
struct B { void Fb() {std::cout << "B" << std::endl; } };

typedef boost::variant< A, B > MyVariants;
typedef std::map< const int, MyVariants > MyVariantsMap;
typedef std::pair< const int, MyVariants > MyVariantsMapPair;

struct H
{
  H( std::initializer_list< MyVariantsMapPair > initialize_list ) : myVariantsMap( initialize_list ) {}

  MyVariantsMap myVariantsMap;
};


class Visitor
    : public boost::static_visitor<>
{
public:

    void operator()(A& a) const
    {
        a.Fa();
    }

    void operator()(B& b) const
    {
        b.Fb();
    }

};

int main()
{
  H h { { 33, A {} }, { 44, B { } } };

  auto myAVariant = h.myVariantsMap[ 33 ];
  auto myBVariant = h.myVariantsMap[ 44 ];

  boost::apply_visitor(Visitor(), myAVariant);
  boost::apply_visitor(Visitor(), myBVariant);

  return 0;
}

live example

m.s.
  • 16,063
  • 7
  • 53
  • 88