0

I have a class with a single member that is a boost::variant of two types: a vector of integers and a vector of the containing class objects (the latter obviously needs to be done with the help of recursive_wrapper). The code for the class is below

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

#include <vector>

class TestVariant
{
public:

    typedef boost::variant< std::vector<int>, boost::recursive_wrapper<std::vector<TestVariant> > > StorageType;

    TestVariant():
        m_value{ std::vector<int>{} }
    {}

    TestVariant(const TestVariant& other):
        m_value{ other.m_value }
    {}

    TestVariant& operator=(const TestVariant& other)
    {
        m_value = other.m_value;

        return *this;
    }

    TestVariant(TestVariant&& other):
        m_value{ std::move(other.m_value) }
    {}

    TestVariant& operator=(TestVariant&& other)
    {
        m_value = std::move(other.m_value);

        return *this;
    }

    TestVariant(const std::vector<int>& value):
        m_value{ value }
    {}

    TestVariant(std::vector<int>&& value):
        m_value{ std::move(value) }
    {}

    TestVariant(const std::vector<TestVariant>& value):
        m_value{ value }
    {}

    TestVariant(std::vector<TestVariant>&& value):
        m_value{ std::move(value) }
    {}

private:

    StorageType m_value;
};

When I try using this class by creating a vector of TestVariant and emplacing an instance of a recursive instance of TestVariant as below

std::vector<TestVariant> v;

v.emplace_back(std::vector<TestVariant>{ std::vector<TestVariant>{}, std::vector<int>{} }); // access violation!

I get an "access violation" exception under MSVS 2013 and Boost ver 1.53 (I know this is an old version of Boost, but I am organisationally constrained to using it at the moment). The same code on coliru works fine (see here).

What is even stranger is that if I switch the order of the two vectors, everything seems to be fine in MSVS 2013

std::vector<TestVariant> v;

v.emplace_back(std::vector<TestVariant>{std::vector<int>{}, std::vector<TestVariant>{} }); // works!

Any ideas? I have been trying to solve this for a day now...

  • 1
    it wouldn't be unusual to find that there is a bug is MSVS2013 or an old version of boost. This might be a good opportunity to argue that your organisation ought to do the right thing and upgrade? – Richard Hodges May 11 '16 at 18:32
  • @RichardHodges I could not agree more, but the cogs turn slowly and, in the meantime, I do need a workaround... – Alexander Kabanov May 12 '16 at 07:13
  • does sehe's solution help? I'd offer to try it but since it cost me 2 days to get vs2015 installed on my Windows computer I don't dare try a side-by-side install. These days if I need to write code for Windows I use clang or Cygwin. I just don't trust Microsoft... – Richard Hodges May 12 '16 at 09:25

1 Answers1

0

This indeed seems to be one of many bugs with uniform initialization/initializer lists. The code is "fine" (in the sense that that doesn't trigger UB)

If it's anything similar to the bugs I ran into, you could try to specify the typenames explicitly:

v.emplace_back(std::vector<TestVariant>{ 
     TestVariant(std::vector<TestVariant>{}), 
     TestVariant(std::vector<int>{}) }); 
sehe
  • 374,641
  • 47
  • 450
  • 633