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-26 09:41:33


#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 zadirion@…):

 Replying to [comment:2 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.

 I must point out the fix you posted does not compile in Visual Studio
 2012. The templated using syntax and the = default and = delete modifiers
 are not implemented in VS2012

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