[Boost-bugs] [Boost C++ Libraries] #11602: boost.variant constructor accepts any type as parameter

Subject: [Boost-bugs] [Boost C++ Libraries] #11602: boost.variant constructor accepts any type as parameter
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2015-08-31 12:00:06


#11602: boost.variant constructor accepts any type as parameter
------------------------------+---------------------
 Reporter: piotrwn1@… | Owner: ebf
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: variant
  Version: Boost 1.58.0 | Severity: Problem
 Keywords: |
------------------------------+---------------------
 There is one "converting constructor" in boost.variant which accepts any
 type - even those which are not convertible to instantiation types of
 boost.variant. This causes that writing function accepting some specific
 variant instantiation cause that this function is on candidate list of any
 type in your program.

 The problem is with this constructor:


 {{{
     template <typename T>
     variant(const T& operand)
     {
         convert_construct(operand, 1L);
     }

 }}}

 And the small code presenting the issue:

 {{{
 #include <iostream>
 #include <boost/variant.hpp>

 // types not related in any way
 class A {};
 class B {};
 class C {};
 class D {};

 using ABC_variant = boost::variant<A,B,C>;

 std::ostream& operator << (std::ostream& os, const ABC_variant&)
 {
         return os << "ABC";
 }

 int main() {
         D d;
         std::cout << d;
 }
 }}}

 As described in [http://stackoverflow.com/questions/32275725/boostvariant-
 construction-weirdness-its-ctor-accepts-everything]

 compiler (gcc4.9) tries to use ostream operator with this diagnostic:

 /usr/include/boost/variant/variant.hpp:1591:38: error: no matching
 function for call to 'boost::variant<A, B,
 C>::initializer::initialize(void*, D&)'
                initializer::initialize(

 However it should simple report that ostream operator for D is missing.

 One simple way is to declare this boost.variant constructor as explicit
 (what probably would impact to many client code) or to make some
 restriction in this constructor like this C++11 way:


 {{{
 template <typename T, typename ...C>
 struct IsAnyOf;

 template <typename T, typename ...C>
 struct IsAnyOf<T,T,C...> : std::true_type {};

 template <typename T>
 struct IsAnyOf<T> : std::false_type {};

 template <typename T, typename C1, typename ...C>
 struct IsAnyOf<T,C1,C...> : IsAnyOf<T, C...> {};

 template <typename T,
           typename EnableIf = typename
 std::enable_if<IsAnyOf<VariantType...>::value>::type>
         variant(const T& operand)


 }}}

 BR,
 Piotr Nycz (piotrwn1 @ gmail com)

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/11602>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:18 UTC