1// Copyright (C) 2012-2015 Free Software Foundation, Inc.
2//
3// This file is part of the GNU ISO C++ Library.  This library is free
4// software; you can redistribute it and/or modify it under the
5// terms of the GNU General Public License as published by the
6// Free Software Foundation; either version 3, or (at your option)
7// any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License along
15// with this library; see the file COPYING3.  If not see
16// <http://www.gnu.org/licenses/>.
17
18// { dg-do compile }
19// { dg-options "-std=gnu++11 -fno-access-control" }
20
21// libstdc++/52591
22
23#include <deque>
24#include <memory>
25#include <type_traits>
26
27
28// As an extension we allow move-assignment of std::deque when the element
29// type is not MoveAssignable, as long as the allocator type propagates or
30// is known to always compare equal.
31
32struct C
33{
34    C& operator=(C&&) = delete;
35};
36
37template<typename T>
38struct A1 : std::allocator<T>
39{
40  template<typename U> struct rebind { typedef A1<U> other; };
41
42  A1() = default;
43  template<typename U> A1(const A1<U>&) { }
44
45  using propagate_on_container_move_assignment = std::true_type;
46};
47
48void test01()
49{
50  using test_type = std::deque<C, A1<C>>;
51  static_assert(std::is_move_assignable<test_type>::value,
52      "deque is move-assignable if allocator propagates");
53}
54
55template<typename T>
56struct A2 : std::allocator<T>
57{
58  template<typename U> struct rebind { typedef A2<U> other; };
59
60  A2() = default;
61  template<typename U> A2(const A2<U>&) { }
62
63  using propagate_on_container_move_assignment = std::false_type;
64};
65
66namespace __gnu_cxx
67{
68  template<typename T>
69    struct __allocator_always_compares_equal<A2<T>> : std::true_type
70    { };
71}
72
73void test02()
74{
75  using test_type = std::deque<C, A2<C>>;
76  static_assert(std::is_nothrow_move_assignable<test_type>::value,
77      "deque is nothrow move-assignable if allocator is always equal");
78}
79