Index: include/string =================================================================== --- include/string +++ include/string @@ -311,6 +311,13 @@ bool __invariants() const; }; +template::value_type>> +basic_string(InputIterator, InputIterator, Allocator = Allocator()) + -> basic_string::value_type, + char_traits::value_type>, + Allocator>; // C++17 + template basic_string operator+(const basic_string& lhs, @@ -1481,6 +1488,18 @@ friend basic_string operator+<>(const basic_string&, value_type); }; +#if _LIBCPP_STD_VER > 14 +template::value_type, + class _Allocator = allocator<_CharT>, + class = typename enable_if<__is_input_iterator<_InputIterator>::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type + > +basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> basic_string<_CharT, char_traits<_CharT>, _Allocator>; +#endif + + template inline _LIBCPP_INLINE_VISIBILITY void Index: test/std/strings/basic.string/string.cons/iter_alloc.fail.cpp =================================================================== --- test/std/strings/basic.string/string.cons/iter_alloc.fail.cpp +++ test/std/strings/basic.string/string.cons/iter_alloc.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 + +// template::value_type>> +// basic_string(InputIterator, InputIterator, Allocator = Allocator()) +// -> basic_string::value_type, +// char_traits::value_type>, +// Allocator>; +// +// The deduction guide shall not participate in overload resolution if InputIterator +// is a type that does not qualify as an input iterator, or if Allocator is a type +// that does not qualify as an allocator. + + +#include +#include +#include +#include + +#include "test_macros.h" + +class NotAnItertor {}; + +template +class NotAnAllocator {}; + +int main() +{ + { // Not an iterator at all + std::basic_string s1{NotAnItertor{}, NotAnItertor{}, std::allocator{}}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}} + } + { // Not an input iterator + const char16_t* s = u"12345678901234"; + std::basic_string s0; + std::basic_string s1{std::back_insert_iterator(s0), + std::back_insert_iterator(s0), + std::allocator{}}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}} + } + { // Not an allocator + const wchar_t* s = L"12345678901234"; + std::basic_string s1{s, s+10, NotAnAllocator{}}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}} + } +} Index: test/std/strings/basic.string/string.cons/iter_alloc.pass.cpp =================================================================== --- test/std/strings/basic.string/string.cons/iter_alloc.pass.cpp +++ test/std/strings/basic.string/string.cons/iter_alloc.pass.cpp @@ -13,6 +13,18 @@ // basic_string(InputIterator begin, InputIterator end, // const Allocator& a = Allocator()); +// template::value_type>> +// basic_string(InputIterator, InputIterator, Allocator = Allocator()) +// -> basic_string::value_type, +// char_traits::value_type>, +// Allocator>; +// +// The deduction guide shall not participate in overload resolution if InputIterator +// is a type that does not qualify as an input iterator, or if Allocator is a type +// that does not qualify as an allocator. + + #include #include #include @@ -116,4 +128,48 @@ test(input_iterator(s), input_iterator(s+50), A()); } #endif + +// Test deduction guides +#if TEST_STD_VER > 14 + { + const char* s = "12345678901234"; + std::basic_string s1{s, s+10, std::allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == 10); + assert(s1.compare(0, s1.size(), s, s1.size()) == 0); + } + { + const wchar_t* s = L"12345678901234"; + std::basic_string s1{s, s+10, test_allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == 10); + assert(s1.compare(0, s1.size(), s, s1.size()) == 0); + } + { + const char16_t* s = u"12345678901234"; + std::basic_string s1{s, s+10, min_allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == 10); + assert(s1.compare(0, s1.size(), s, s1.size()) == 0); + } + { + const char32_t* s = U"12345678901234"; + std::basic_string s1{s, s+10, explicit_allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == 10); + assert(s1.compare(0, s1.size(), s, s1.size()) == 0); + } +#endif }