Boost logo

Boost :

Subject: Re: [boost] [variant] Breaking change introduced by variadic support
From: Antony Polukhin (antoshkka_at_[hidden])
Date: 2014-01-21 02:37:19


2014/1/21 Agustín K-ballo Bergé <kaballo86_at_[hidden]>
<...>

> While trying to make _Boost.Spirit_ work after the breaking changes, I
> found a problem with the following snippet:
>
> #include <boost/variant.hpp>
> #include <boost/mpl/bool.hpp>
>
> template <typename T>
> struct is_container : boost::mpl::false_ {};
>
> template <typename T>
> struct is_container<boost::variant<T>> : is_container<T> {};
>
> template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
> struct is_container<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
> : boost::mpl::bool_<is_container<T0>::value
> ||
> is_container<boost::variant<BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)>>::value>
> // #13
> {};
>
> int main()
> {
> is_container<boost::variant<double, int>>::value;
> }
>
> If I understand correctly, this should work for both the variadic and
> non-variadic cases. However, trying this with both MSVC2013 and NovCTP13
> gives the following error:
>
> > main.cpp(13): error C2976: 'boost::variant' : too few template arguments
>

This looks like an issue in MSVC2013. MSVC2013 choose to use variadic
tempalte version even if there is a specialization with one template.
Following code must reproduce it (did not check it):

#include <boost/mpl/bool.hpp>

template <typename T0, typename TN...>
struct variant{};

template <typename T>
struct is_container : boost::mpl::false_ {};

template <typename T0, typename TN...>
struct is_container<variant<T0, TN...>>
  : boost::mpl::bool_<is_container<T0>::value ||
is_container<variant<TN...>>::value>
{};

> The code works fine for GCC4.8.2 (both for C++03 and C++11), and it works
> with Clang 3.3 too although it does not use the variadic version (why?).

This may be an issue with Boost.Config. I've tested on clang 3.0 and it
used the variadic templates.

> Is this a bug with MSVC, or did I do something wrong? If the former, I
> would suggest sticking with the non-variadic approach for MSVC, since this
> seems to be a pretty basic use case.

Some GCCs prior to 4.7 have variadic templates support, but Variant does
not use them because of compiler implementation issues. Looks like the same
approach must be taken with MSVC2013.

Also, feel free to use the previous code as a base for a regression test.

Thanks! I'll commit this test case in a few days.

-- 
Best regards,
Antony Polukhin

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