Re: [Boost-bugs] [Boost C++ Libraries] #7364: ambiguity error constructing std::vector from assign::list_of

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #7364: ambiguity error constructing std::vector from assign::list_of
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2012-09-19 15:35:27


#7364: ambiguity error constructing std::vector from assign::list_of
--------------------------------------+-------------------------------------
  Reporter: eric_niebler | Owner: nesotto
      Type: Bugs | Status: new
 Milestone: To Be Determined | Component: assign
   Version: Boost Development Trunk | Severity: Problem
Resolution: | Keywords:
--------------------------------------+-------------------------------------

Comment (by eric_niebler):

 Below is an implementation of `list_of` that addresses the issue for C++11
 compilers.

 {{{
 #include <iostream>
 #include <iterator>
 #include <algorithm>
 #include <deque>
 #include <vector>
 #include <utility>
 #include <type_traits>

 template<typename T>
 using uncvref = typename std::remove_cv<typename
 std::remove_reference<T>::type>::type;

 template<typename T>
 struct generic_list;

 template<typename T>
 generic_list<uncvref<T>> list_of(T && t);

 template<typename T>
 struct generic_list
 {
 private:
     std::deque<T> values;

     friend generic_list<T> list_of<>(T && t);
     friend generic_list<T> list_of<>(T & t);
     friend generic_list<T> list_of<>(T const & t);
     generic_list() = default;

 public:
     generic_list(generic_list &&) = default;
     generic_list(generic_list const &) = delete;
     generic_list &operator=(generic_list &&) = delete;
     generic_list &operator=(generic_list const &) = delete;

     template<typename U>
     generic_list & operator()(U && t)
 noexcept(noexcept(values.push_back(static_cast<U &&>(t))))
     {
         values.push_back(static_cast<U &&>(t));
         return *this;
     }

     template<typename Container, typename =
 decltype(Container(std::make_move_iterator(values.begin()),
 std::make_move_iterator(values.end())))>
     operator Container()
 noexcept(noexcept(Container(Container(std::make_move_iterator(values.begin()),
 std::make_move_iterator(values.end())))))
     {
         return Container(std::make_move_iterator(values.begin()),
 std::make_move_iterator(values.end()));
     }
 };

 template<typename T>
 inline generic_list<uncvref<T>> list_of(T && t)
 {
     return std::move(generic_list<uncvref<T>>()(static_cast<T &&>(t)));
 }

 struct moveable
 {
     moveable() = default;
     moveable(moveable &&) = default;
     moveable(moveable const &) = delete;
     moveable &operator=(moveable &&) = default;
     moveable &operator=(moveable const &) = delete;
 };

 int main()
 {
     std::vector<int> i(list_of(1));
     std::copy(i.begin(), i.end(), std::ostream_iterator<int>(std::cout,
 "\n"));

     std::vector<moveable> j = list_of(moveable())(moveable());
 }
 }}}

 The trick to fixing the ambiguity error is the defaulted template
 parameter on `operator Container` that only allows the conversion if the
 container can be constructed from a pair of iterators.

 HTH.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/7364#comment:2>
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:10 UTC