Boost logo

Boost :

Subject: Re: [boost] [variant] awkward recursion
From: Dave Abrahams (dave_at_[hidden])
Date: 2012-10-31 14:02:25


on Mon Oct 29 2012, Mathias Gaunard <mathias.gaunard-AT-ens-lyon.org> wrote:

> On 29/10/12 22:15, Dave Abrahams wrote:
>>
>> on Mon Oct 29 2012, Agustín K-ballo Bergé <kaballo86-AT-hotmail.com> wrote:
>>
>>> On 29/10/2012 04:29 p.m., Dave Abrahams wrote:
>>>> In the abstract, json looks like:
>
>>>>
>>>> struct null {};
>>>> typedef std::map<std::string, value> object;
>>>> typedef std::vector<value> array;
>>>>
>>>> typedef variant<
>>>> null, std::string, double, object, array, bool
>>>> > value;
>>>
>>> Keep in mind that instantiating a standard container with an
>>> incomplete type will yield undefined behavior, and that `variant` has
>>> to instantiate both `object` and `array` to know their size. In my own
>>> JSON attempt I have used Boost.Containers, which do guarantee defined
>>> behavior when instantiated with incomplete types.
>>
>> I haven't instantiated anything at that point in the code, though.
>
> According to the code you provided, you do instantiate the std::vector
> class template with an incomplete type in both the no_wrapper and
> wrapper cases.

Actually, I think the wrapper case is perfectly legal... and I can prove
it. The following compiles:

--8<---------------cut here---------------start------------->8---
namespace wrapper
{
  struct value;
  
  template <class T, class U>
  struct mymap : std::map<T,U>
  {
      enum { _size = sizeof(T)+sizeof(U) }; // error if T or U are incomplete
  };
  typedef mymap<std::string, value> object;
  
  template <class T>
  struct myvec : std::vector<T>
  {
      enum { _size = sizeof(T) }; // error if T or U are incomplete
  };
  
  typedef myvec<value> array;

  typedef variant<
      null, std::string, double,
      recursive_wrapper<object>,
      recursive_wrapper<array>,
      bool
> value_base;

  struct value : value_base
  {
    value() {};
    
    template <class T>
    value(T const& x) : value_base(x) {} // no move; I'm in C++03-land

    value& operator=(value const& x) {
      value_base const& x_ = x;
      value_base::operator=(x_);
      return *this;
    }
  };
}

wrapper::value x;
--8<---------------cut here---------------end--------------->8---

-- 
Dave Abrahams
BoostPro Computing                  Software Development        Training
http://www.boostpro.com             Clang/LLVM/EDG Compilers  C++  Boost

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk