From 5b8b8b5dce587f1e5a4a31cc24f09b18bd53ff9a Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 22 May 2018 01:57:53 +0000 Subject: [PATCH] Deduction guides for the container adaptors - queue, stack, and priority_queue llvm-svn: 332927 --- libcxx/include/queue | 66 ++++++++++++++ libcxx/include/stack | 22 +++++ .../queue/queue.cons/deduct.fail.cpp | 46 ++++++++++ .../queue/queue.cons/deduct.pass.cpp | 89 ++++++++++++++++++ .../stack/stack.cons/deduct.fail.cpp | 53 +++++++++++ .../stack/stack.cons/deduct.pass.cpp | 91 +++++++++++++++++++ 6 files changed, 367 insertions(+) create mode 100644 libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.fail.cpp create mode 100644 libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp create mode 100644 libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.fail.cpp create mode 100644 libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp diff --git a/libcxx/include/queue b/libcxx/include/queue index 80546fd81ad1..4677e52ae3a7 100644 --- a/libcxx/include/queue +++ b/libcxx/include/queue @@ -69,6 +69,12 @@ public: void swap(queue& q) noexcept(is_nothrow_swappable_v) }; +template + queue(Container) -> queue; // C++17 + +template + queue(Container, Allocator) -> queue; // C++17 + template bool operator==(const queue& x,const queue& y); @@ -157,6 +163,20 @@ public: is_nothrow_swappable_v) }; +template +priority_queue(Compare, Container) + -> priority_queue; // C++17 + +template::value_type>, + class Container = vector::value_type>> +priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) + -> priority_queue::value_type, Container, Compare>; // C++17 + +template +priority_queue(Compare, Container, Allocator) + -> priority_queue; // C++17 + template void swap(priority_queue& x, priority_queue& y) @@ -321,6 +341,22 @@ public: operator< (const queue<_T1, _C1>& __x,const queue<_T1, _C1>& __y); }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template::value, nullptr_t>::type +> +queue(_Container) + -> queue; + +template::value, nullptr_t>::type, + class = typename enable_if< __is_allocator<_Alloc>::value, nullptr_t>::type +> +queue(_Container, _Alloc) + -> queue; +#endif + template inline _LIBCPP_INLINE_VISIBILITY bool @@ -515,6 +551,36 @@ public: __is_nothrow_swappable::value); }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template ::value, nullptr_t>::type, + class = typename enable_if::value, nullptr_t>::type +> +priority_queue(_Compare, _Container) + -> priority_queue; + +template::value_type>, + class _Container = vector::value_type>, + class = typename enable_if< __is_input_iterator<_InputIterator>::value, nullptr_t>::type, + class = typename enable_if::value, nullptr_t>::type, + class = typename enable_if::value, nullptr_t>::type +> +priority_queue(_InputIterator, _InputIterator, _Compare = _Compare(), _Container = _Container()) + -> priority_queue::value_type, _Container, _Compare>; + +template::value, nullptr_t>::type, + class = typename enable_if::value, nullptr_t>::type, + class = typename enable_if< __is_allocator<_Alloc>::value, nullptr_t>::type +> +priority_queue(_Compare, _Container, _Alloc) + -> priority_queue; +#endif + template inline priority_queue<_Tp, _Container, _Compare>::priority_queue(const _Compare& __comp, diff --git a/libcxx/include/stack b/libcxx/include/stack index 7b81ade1f5d0..2b3f8aea19e6 100644 --- a/libcxx/include/stack +++ b/libcxx/include/stack @@ -61,6 +61,12 @@ public: void swap(stack& c) noexcept(is_nothrow_swappable_v) }; +template + stack(Container) -> stack; // C++17 + +template + stack(Container, Allocator) -> stack; // C++17 + template bool operator==(const stack& x, const stack& y); template @@ -229,6 +235,22 @@ public: operator< (const stack& __x, const stack& __y); }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template::value, nullptr_t>::type +> +stack(_Container) + -> stack; + +template::value, nullptr_t>::type, + class = typename enable_if< __is_allocator<_Alloc>::value, nullptr_t>::type + > +stack(_Container, _Alloc) + -> stack; +#endif + template inline _LIBCPP_INLINE_VISIBILITY bool diff --git a/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.fail.cpp b/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.fail.cpp new file mode 100644 index 000000000000..de564de6f0ef --- /dev/null +++ b/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.fail.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +#include +#include +#include +#include +#include + + +int main() +{ +// Test the explicit deduction guides + { +// queue(const Container&, const Alloc&); +// The '45' is not an allocator + std::queue que(std::list{1,2,3}, 45); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'queue'}} + } + + { +// queue(const queue&, const Alloc&); +// The '45' is not an allocator + std::queue source; + std::queue que(source, 45); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'queue'}} + } + +// Test the implicit deduction guides + { +// queue (allocator &) + std::queue que((std::allocator())); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'queue'}} +// Note: The extra parens are necessary, since otherwise clang decides it is a function declaration. +// Also, we can't use {} instead of parens, because that constructs a +// stack, allocator>> + } + +} diff --git a/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp new file mode 100644 index 000000000000..480da46713c9 --- /dev/null +++ b/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + + +// template +// queue(Container) -> queue; +// +// template +// queue(Container, Allocator) -> queue; + + +#include +#include +#include +#include +#include +#include // INT_MAX + +#include "test_macros.h" +#include "test_iterators.h" +#include "test_allocator.h" + +struct A {}; + +int main() +{ + +// Test the explicit deduction guides + { + std::list l{0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::queue que(l); + + static_assert(std::is_same_v>>, ""); + assert(que.size() == l.size()); + assert(que.back() == l.back()); + } + + { + std::list> l{10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; + std::queue que(l, test_allocator(0,2)); // different allocator + static_assert(std::is_same_v>>, ""); + static_assert(std::is_same_v, ""); + assert(que.size() == 10); + assert(que.back() == 19); +// I'd like to assert that we've gotten the right allocator in the queue, but +// I don't know how to get at the underlying container. + } + +// Test the implicit deduction guides + { +// We don't expect this one to work - no way to implicitly get value_type +// std::queue que(std::allocator()); // queue (allocator &) + } + + { + std::queue source; + std::queue que(source); // queue(queue &) + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + assert(que.size() == 0); + } + + { +// This one is odd - you can pass an allocator in to use, but the allocator +// has to match the type of the one used by the underlying container + typedef short T; + typedef test_allocator A; + typedef std::deque C; + + C c{0,1,2,3}; + std::queue source(c); + std::queue que(source, A(2)); // queue(queue &, allocator) + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v, ""); + assert(que.size() == 4); + assert(que.back() == 3); + } + +} diff --git a/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.fail.cpp b/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.fail.cpp new file mode 100644 index 000000000000..e14965adadcb --- /dev/null +++ b/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.fail.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + + +// template ::value_type>> +// vector(InputIterator, InputIterator, Allocator = Allocator()) +// -> vector::value_type, Allocator>; +// + + +#include +#include +#include +#include +#include + + +int main() +{ +// Test the explicit deduction guides + { +// stack(const Container&, const Alloc&); +// The '45' is not an allocator + std::stack stk(std::list({1,2,3}), 45); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'stack'}} + } + + { +// stack(const stack&, const Alloc&); +// The '45' is not an allocator + std::stack source; + std::stack stk(source, 45); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'stack'}} + } + +// Test the implicit deduction guides + { +// stack (allocator &) + std::stack stk((std::allocator())); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'stack'}} +// Note: The extra parens are necessary, since otherwise clang decides it is a function declaration. +// Also, we can't use {} instead of parens, because that constructs a +// stack, allocator>> + } + +} diff --git a/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp new file mode 100644 index 000000000000..4ae11376b2b0 --- /dev/null +++ b/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + + +// template +// stack(Container) -> stack; +// +// template +// stack(Container, Allocator) -> stack; + + +#include +#include +#include +#include +#include +#include +#include // INT_MAX + +#include "test_macros.h" +#include "test_iterators.h" +#include "test_allocator.h" + +struct A {}; + +int main() +{ + +// Test the explicit deduction guides + { + std::vector v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::stack stk(v); + + static_assert(std::is_same_v>>, ""); + assert(stk.size() == v.size()); + assert(stk.top() == v.back()); + } + + { + std::list> l{10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; + std::stack stk(l, test_allocator(0,2)); // different allocator + static_assert(std::is_same_v>>, ""); + static_assert(std::is_same_v, ""); + assert(stk.size() == 10); + assert(stk.top() == 19); +// I'd like to assert that we've gotten the right allocator in the stack, but +// I don't know how to get at the underlying container. + } + +// Test the implicit deduction guides + + { +// We don't expect this one to work - no way to implicitly get value_type +// std::stack stk(std::allocator()); // stack (allocator &) + } + + { + std::stack source; + std::stack stk(source); // stack(stack &) + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + assert(stk.size() == 0); + } + + { +// This one is odd - you can pass an allocator in to use, but the allocator +// has to match the type of the one used by the underlying container + typedef short T; + typedef test_allocator A; + typedef std::deque C; + + C c{0,1,2,3}; + std::stack source(c); + std::stack stk(source, A(2)); // stack(stack &, allocator) + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v, ""); + assert(stk.size() == 4); + assert(stk.top() == 3); + } + +}