Boost logo

Boost :

Subject: Re: [boost] [variant] Breaking change introduced by variadic support
From: Antony Polukhin (antoshkka_at_[hidden])
Date: 2014-01-18 12:32:35


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

> The recent changes to introduce variadic support to `variant` introduce
> breaking changes in the documented macros. When variadic support is
> detected, `BOOST_VARIANT_LIMIT_TYPES` is not defined and
> `BOOST_VARIANT_ENUM_[SHIFTED_]PARAMS` uses variadic templates instead of
> enumerating parameters.
>
> This is a breaking change in the documented interface, and one that
> requires all but the simplest use cases to be rewritten. For instance, this
> breaks _Boost.Spirit_ support of `variant` (https://svn.boost.org/trac/
> boost/ticket/9238), requiring two different implementations to be
> provided.
>
> Is this the preferred path to take? I would suggest instead to keep the
> macros as documented at all times, and let the user handle the variadic
> case manually. This would allow users to support both variadic and
> non-variadic `variant`s up to a certain limit with a single code case
> (without breaking the documented interface), and result in cleaner code for
> those cases that only target compilers with variadic support. There's no
> point in using a macro if it won't work for both cases.
>

Unfortunately this will make previous code just "look like" it works.
Variadic template version of variant (`variant<T0, TN...>`) is not same as
variant generated by BOOST_VARIANT_LIMIT_TYPES and preprocessor
(`variant<T0, T1, T2, T3, T4, T5, T6, T7, T8>`). Leaving
BOOST_VARIANT_LIMIT_TYPES defined will result in many-many hard detectable
template errors.

Here is an example

template <class T> struct is_variant: boost::false_type {};

template </*`class TX` generated by handwritten preprocessor code and
BOOST_VARIANT_LIMIT_TYPES*/>
struct is_variant< variant</*`TX` generated by handwritten preprocessor
code and BOOST_VARIANT_LIMIT_TYPES*/> >
: boost::true_type {};

Following code will produce different results, depending on availability of
variadic templates:
is_variant<variant<int, char> >::value
That's because *there is* a difference between variant<T0, TN...> and
variant<T0, T1, T2, T3, T4, T5, T6, T7, T8>

I've put a lot of effort to make transition as smooth as possible:
* users that use BOOST_VARIANT_ENUM_[SHIFTED_]PARAMS shall notice no change:
// BOOST_VARIANT_ENUM_PARAMS(class Something) => class
Something0, class... SomethingN
// BOOST_VARIANT_ENUM_PARAMS(Something) => Something0,
SomethingN...
* users are free to define BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES and
do not use variadic templates version at all.
* users that use BOOST_VARIANT_LIMIT_TYPES won't get silent templates
errors and will be able to take care about the issues.

Any ideas about how to make transition smoother are welcomed!

-- 
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