[libc++] Fix PR 31938 - std::basic_string constructors use non-deductible parameter types.

Summary:
This patch fixes http://llvm.org/PR31938. The description below is copy/pasted from the bug:

The standard says:

template<class charT, class traits = char_traits<charT>,
         class Allocator = allocator<charT>>
class basic_string {
  using value_type = typename traits::char_type;
  // ...
  basic_string(const charT* s, const Allocator& a = Allocator());
};

libc++ actually chooses to declare the constructor as

  basic_string(const value_type* s, const Allocator& a = Allocator());

The implicit deduction guides from class template argument deduction make what was previously an implementation detail visible:

std::basic_string s = "foo"; // error, can't deduce charT.

The constructor in question is in the libc++ DSO, but fortunately it looks like fixing this will not result in an ABI break.


@rsmith How does this look? I did more than just the constructors mentioned in the PR, but IDK how far to take it.


Reviewers: mclow.lists, rsmith

Reviewed By: rsmith

Subscribers: cfe-commits, rsmith

Differential Revision: https://reviews.llvm.org/D29863

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@295393 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2017-02-17 01:17:10 +00:00
parent 4203bfb5d3
commit 0eaf2e8474
4 changed files with 336 additions and 27 deletions

View File

@@ -775,22 +775,22 @@ public:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
basic_string(basic_string&& __str, const allocator_type& __a); basic_string(basic_string&& __str, const allocator_type& __a);
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
_LIBCPP_INLINE_VISIBILITY basic_string(const value_type* __s); _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s);
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
basic_string(const value_type* __s, const allocator_type& __a); basic_string(const _CharT* __s, const _Allocator& __a);
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
basic_string(const value_type* __s, size_type __n); basic_string(const _CharT* __s, size_type __n);
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
basic_string(const value_type* __s, size_type __n, const allocator_type& __a); basic_string(const _CharT* __s, size_type __n, const _Allocator& __a);
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
basic_string(size_type __n, value_type __c); basic_string(size_type __n, _CharT __c);
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
basic_string(size_type __n, value_type __c, const allocator_type& __a); basic_string(size_type __n, _CharT __c, const _Allocator& __a);
basic_string(const basic_string& __str, size_type __pos, size_type __n, basic_string(const basic_string& __str, size_type __pos, size_type __n,
const allocator_type& __a = allocator_type()); const _Allocator& __a = _Allocator());
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
basic_string(const basic_string& __str, size_type __pos, basic_string(const basic_string& __str, size_type __pos,
const allocator_type& __a = allocator_type()); const _Allocator& __a = _Allocator());
template<class _Tp> template<class _Tp>
basic_string(const _Tp& __t, size_type __pos, size_type __n, basic_string(const _Tp& __t, size_type __pos, size_type __n,
const allocator_type& __a = allocator_type(), const allocator_type& __a = allocator_type(),
@@ -798,7 +798,7 @@ public:
_LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_INLINE_VISIBILITY explicit
basic_string(__self_view __sv); basic_string(__self_view __sv);
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
basic_string(__self_view __sv, const allocator_type& __a); basic_string(__self_view __sv, const _Allocator& __a);
template<class _InputIterator> template<class _InputIterator>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
basic_string(_InputIterator __first, _InputIterator __last); basic_string(_InputIterator __first, _InputIterator __last);
@@ -807,9 +807,9 @@ public:
basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a); basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a);
#ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
basic_string(initializer_list<value_type> __il); basic_string(initializer_list<_CharT> __il);
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
basic_string(initializer_list<value_type> __il, const allocator_type& __a); basic_string(initializer_list<_CharT> __il, const _Allocator& __a);
#endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
inline ~basic_string(); inline ~basic_string();
@@ -1557,7 +1557,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_ty
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s) basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s)
{ {
_LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr"); _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr");
__init(__s, traits_type::length(__s)); __init(__s, traits_type::length(__s));
@@ -1568,7 +1568,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s)
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s, const allocator_type& __a) basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, const _Allocator& __a)
: __r_(__a) : __r_(__a)
{ {
_LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*, allocator) detected nullptr"); _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*, allocator) detected nullptr");
@@ -1580,7 +1580,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s, c
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s, size_type __n) basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_type __n)
{ {
_LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr"); _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr");
__init(__s, __n); __init(__s, __n);
@@ -1591,7 +1591,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s, s
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s, size_type __n, const allocator_type& __a) basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_type __n, const _Allocator& __a)
: __r_(__a) : __r_(__a)
{ {
_LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr"); _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr");
@@ -1615,7 +1615,8 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __st
} }
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str, const allocator_type& __a) basic_string<_CharT, _Traits, _Allocator>::basic_string(
const basic_string& __str, const allocator_type& __a)
: __r_(__a) : __r_(__a)
{ {
if (!__str.__is_long()) if (!__str.__is_long())
@@ -1694,7 +1695,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c)
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, value_type __c) basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c)
{ {
__init(__n, __c); __init(__n, __c);
#if _LIBCPP_DEBUG_LEVEL >= 2 #if _LIBCPP_DEBUG_LEVEL >= 2
@@ -1704,7 +1705,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, value_typ
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, value_type __c, const allocator_type& __a) basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c, const _Allocator& __a)
: __r_(__a) : __r_(__a)
{ {
__init(__n, __c); __init(__n, __c);
@@ -1714,8 +1715,9 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, value_typ
} }
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str, size_type __pos, size_type __n, basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str,
const allocator_type& __a) size_type __pos, size_type __n,
const _Allocator& __a)
: __r_(__a) : __r_(__a)
{ {
size_type __str_sz = __str.size(); size_type __str_sz = __str.size();
@@ -1730,7 +1732,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __st
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str, size_type __pos, basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str, size_type __pos,
const allocator_type& __a) const _Allocator& __a)
: __r_(__a) : __r_(__a)
{ {
size_type __str_sz = __str.size(); size_type __str_sz = __str.size();
@@ -1768,7 +1770,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(__self_view __sv)
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(__self_view __sv, const allocator_type& __a) basic_string<_CharT, _Traits, _Allocator>::basic_string(__self_view __sv, const _Allocator& __a)
: __r_(__a) : __r_(__a)
{ {
__init(__sv.data(), __sv.size()); __init(__sv.data(), __sv.size());
@@ -1863,7 +1865,8 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first,
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(initializer_list<value_type> __il) basic_string<_CharT, _Traits, _Allocator>::basic_string(
initializer_list<_CharT> __il)
{ {
__init(__il.begin(), __il.end()); __init(__il.begin(), __il.end());
#if _LIBCPP_DEBUG_LEVEL >= 2 #if _LIBCPP_DEBUG_LEVEL >= 2
@@ -1873,7 +1876,9 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(initializer_list<value_t
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(initializer_list<value_type> __il, const allocator_type& __a) basic_string<_CharT, _Traits, _Allocator>::basic_string(
initializer_list<_CharT> __il, const _Allocator& __a)
: __r_(__a) : __r_(__a)
{ {
__init(__il.begin(), __il.end()); __init(__il.begin(), __il.end());

View File

@@ -0,0 +1,300 @@
//===----------------------------------------------------------------------===//
//
// 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
// <string>
// Test that the constructors offered by std::basic_string are formulated
// so they're compatible with implicit deduction guides.
#include <string>
#include <string_view>
#include <cassert>
#include "test_macros.h"
#include "test_allocator.h"
#include "test_iterators.h"
#include "constexpr_char_traits.hpp"
template <class T, class Alloc = std::allocator<T>>
using BStr = std::basic_string<T, std::char_traits<T>, Alloc>;
// Overloads
// using A = Allocator;
// using BS = basic_string
// using BSV = basic_string_view
// ---------------
// (1) basic_string() - NOT TESTED
// (2) basic_string(A const&) - BROKEN
// (3) basic_string(size_type, CharT, const A& = A())
// (4) basic_string(BS const&, size_type, A const& = A())
// (5) basic_string(BS const&, size_type, size_type, A const& = A()) - PARTIALLY BROKEN
// (6) basic_string(const CharT*, size_type, A const& = A())
// (7) basic_string(const CharT*, A const& = A())
// (8) basic_string(InputIt, InputIt, A const& = A()) - BROKEN
// (9) basic_string(BS const&)
// (10) basic_string(BS const&, A const&)
// (11) basic_string(BS&&)
// (12) basic_string(BS&&, A const&)
// (13) basic_string(initializer_list<CharT>, A const& = A())
// (14) basic_string(BSV, A const& = A())
// (15) basic_string(const T&, size_type, size_type, A const& = A()) - BROKEN
int main()
{
using TestSizeT = test_allocator<char>::size_type;
{ // Testing (1)
// Nothing TODO. Cannot deduce without any arguments.
}
{ // Testing (2)
// This overload isn't compatible with implicit deduction guides as
// specified in the standard.
// const test_allocator<char> alloc{};
// std::basic_string s(alloc);
}
{ // Testing (3) w/o allocator
std::basic_string s(6ull, 'a');
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "aaaaaa");
std::basic_string w(2ull, L'b');
ASSERT_SAME_TYPE(decltype(w), std::wstring);
assert(w == L"bb");
}
{ // Testing (3) w/ allocator
std::basic_string s(6ull, 'a', test_allocator<char>{});
ASSERT_SAME_TYPE(decltype(s), BStr<char,test_allocator<char>>);
assert(s == "aaaaaa");
std::basic_string w(2ull, L'b', test_allocator<wchar_t>{});
ASSERT_SAME_TYPE(decltype(w), BStr<wchar_t, test_allocator<wchar_t>>);
assert(w == L"bb");
}
{ // Testing (4) w/o allocator
const std::string sin("abc");
std::basic_string s(sin, (size_t)1);
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "bc");
using WStr = std::basic_string<wchar_t,
constexpr_char_traits<wchar_t>,
test_allocator<wchar_t>>;
const WStr win(L"abcdef");
std::basic_string w(win, (TestSizeT)3);
ASSERT_SAME_TYPE(decltype(w), WStr);
assert(w == L"def");
}
{ // Testing (4) w/ allocator
const std::string sin("abc");
std::basic_string s(sin, (size_t)1, std::allocator<char>{});
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "bc");
using WStr = std::basic_string<wchar_t,
constexpr_char_traits<wchar_t>,
test_allocator<wchar_t>>;
const WStr win(L"abcdef");
std::basic_string w(win, (TestSizeT)3, test_allocator<wchar_t>{});
ASSERT_SAME_TYPE(decltype(w), WStr);
assert(w == L"def");
}
{ // Testing (5) w/o allocator
#if 0 // FIXME: This doesn't work
const std::string sin("abc");
std::basic_string s(sin, (size_t)1, (size_t)3);
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "bc");
using WStr = std::basic_string<wchar_t,
constexpr_char_traits<wchar_t>,
test_allocator<wchar_t>>;
const WStr win(L"abcdef");
std::basic_string w(win, (TestSizeT)2, (TestSizeT)3);
ASSERT_SAME_TYPE(decltype(w), WStr);
assert(w == L"cde");
#endif
}
{ // Testing (5) w/ allocator
const std::string sin("abc");
std::basic_string s(sin, (size_t)1, (size_t)3, std::allocator<char>{});
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "bc");
using WStr = std::basic_string<wchar_t,
constexpr_char_traits<wchar_t>,
test_allocator<wchar_t>>;
const WStr win(L"abcdef");
std::basic_string w(win, (TestSizeT)2, (TestSizeT)3, test_allocator<wchar_t>{});
ASSERT_SAME_TYPE(decltype(w), WStr);
assert(w == L"cde");
}
{ // Testing (6) w/o allocator
std::basic_string s("abc", (size_t)2);
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "ab");
std::basic_string w(L"abcdef", (size_t)3);
ASSERT_SAME_TYPE(decltype(w), std::wstring);
assert(w == L"abc");
}
{ // Testing (6) w/ allocator
std::basic_string s("abc", (size_t)2, std::allocator<char>{});
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "ab");
using WStr = std::basic_string<wchar_t,
std::char_traits<wchar_t>,
test_allocator<wchar_t>>;
std::basic_string w(L"abcdef", (TestSizeT)3, test_allocator<wchar_t>{});
ASSERT_SAME_TYPE(decltype(w), WStr);
assert(w == L"abc");
}
{ // Testing (7) w/o allocator
std::basic_string s("abc");
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "abc");
std::basic_string w(L"abcdef");
ASSERT_SAME_TYPE(decltype(w), std::wstring);
assert(w == L"abcdef");
}
{ // Testing (7) w/ allocator
std::basic_string s("abc", std::allocator<char>{});
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "abc");
using WStr = std::basic_string<wchar_t,
std::char_traits<wchar_t>,
test_allocator<wchar_t>>;
std::basic_string w(L"abcdef", test_allocator<wchar_t>{});
ASSERT_SAME_TYPE(decltype(w), WStr);
assert(w == L"abcdef");
}
{ // (8) w/o allocator
// This overload isn't compatible with implicit deduction guides as
// specified in the standard.
// FIXME: Propose adding an explicit guide to the standard?
}
{ // (8) w/ allocator
// This overload isn't compatible with implicit deduction guides as
// specified in the standard.
// FIXME: Propose adding an explicit guide to the standard?
#if 0
using It = input_iterator<const char*>;
const char* input = "abcdef";
std::basic_string s(It(input), It(input + 3), std::allocator<char>{});
ASSERT_SAME_TYPE(decltype(s), std::string);
#endif
}
{ // Testing (9)
const std::string sin("abc");
std::basic_string s(sin);
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "abc");
using WStr = std::basic_string<wchar_t,
constexpr_char_traits<wchar_t>,
test_allocator<wchar_t>>;
const WStr win(L"abcdef");
std::basic_string w(win);
ASSERT_SAME_TYPE(decltype(w), WStr);
assert(w == L"abcdef");
}
{ // Testing (10)
const std::string sin("abc");
std::basic_string s(sin, std::allocator<char>{});
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "abc");
using WStr = std::basic_string<wchar_t,
constexpr_char_traits<wchar_t>,
test_allocator<wchar_t>>;
const WStr win(L"abcdef");
std::basic_string w(win, test_allocator<wchar_t>{});
ASSERT_SAME_TYPE(decltype(w), WStr);
assert(w == L"abcdef");
}
{ // Testing (11)
std::string sin("abc");
std::basic_string s(std::move(sin));
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "abc");
using WStr = std::basic_string<wchar_t,
constexpr_char_traits<wchar_t>,
test_allocator<wchar_t>>;
WStr win(L"abcdef");
std::basic_string w(std::move(win));
ASSERT_SAME_TYPE(decltype(w), WStr);
assert(w == L"abcdef");
}
{ // Testing (12)
std::string sin("abc");
std::basic_string s(std::move(sin), std::allocator<char>{});
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "abc");
using WStr = std::basic_string<wchar_t,
constexpr_char_traits<wchar_t>,
test_allocator<wchar_t>>;
WStr win(L"abcdef");
std::basic_string w(std::move(win), test_allocator<wchar_t>{});
ASSERT_SAME_TYPE(decltype(w), WStr);
assert(w == L"abcdef");
}
{ // Testing (13) w/o allocator
std::basic_string s({'a', 'b', 'c'});
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "abc");
std::basic_string w({L'a', L'b', L'c'});
ASSERT_SAME_TYPE(decltype(w), std::wstring);
assert(w == L"abc");
}
{ // Testing (13) w/ allocator
std::basic_string s({'a', 'b', 'c'}, test_allocator<char>{});
ASSERT_SAME_TYPE(decltype(s), BStr<char, test_allocator<char>>);
assert(s == "abc");
std::basic_string w({L'a', L'b', L'c'}, test_allocator<wchar_t>{});
ASSERT_SAME_TYPE(decltype(w), BStr<wchar_t, test_allocator<wchar_t>>);
assert(w == L"abc");
}
{ // Testing (14) w/o allocator
std::string_view sv("abc");
std::basic_string s(sv);
ASSERT_SAME_TYPE(decltype(s), std::string);
assert(s == "abc");
using Expect = std::basic_string<wchar_t, constexpr_char_traits<wchar_t>>;
std::basic_string_view<wchar_t, constexpr_char_traits<wchar_t>> BSV(L"abcdef");
std::basic_string w(BSV);
ASSERT_SAME_TYPE(decltype(w), Expect);
assert(w == L"abcdef");
}
{ // Testing (14) w/ allocator
using ExpectS = std::basic_string<char, std::char_traits<char>, test_allocator<char>>;
std::string_view sv("abc");
std::basic_string s(sv, test_allocator<char>{});
ASSERT_SAME_TYPE(decltype(s), ExpectS);
assert(s == "abc");
using ExpectW = std::basic_string<wchar_t, constexpr_char_traits<wchar_t>,
test_allocator<wchar_t>>;
std::basic_string_view<wchar_t, constexpr_char_traits<wchar_t>> BSV(L"abcdef");
std::basic_string w(BSV, test_allocator<wchar_t>{});
ASSERT_SAME_TYPE(decltype(w), ExpectW);
assert(w == L"abcdef");
}
{ // Testing (15)
// This overload isn't compatible with implicit deduction guides as
// specified in the standard.
}
}

View File

@@ -12,6 +12,7 @@
#define _CONSTEXPR_CHAR_TRAITS #define _CONSTEXPR_CHAR_TRAITS
#include <string> #include <string>
#include <cassert>
#include "test_macros.h" #include "test_macros.h"
@@ -118,7 +119,7 @@ template <class _CharT>
TEST_CONSTEXPR_CXX14 _CharT* TEST_CONSTEXPR_CXX14 _CharT*
constexpr_char_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n) constexpr_char_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n)
{ {
_LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); assert(__s2 < __s1 || __s2 >= __s1+__n);
char_type* __r = __s1; char_type* __r = __s1;
for (; __n; --__n, ++__s1, ++__s2) for (; __n; --__n, ++__s1, ++__s2)
assign(*__s1, *__s2); assign(*__s1, *__s2);

View File

@@ -397,6 +397,9 @@ class Configuration(object):
if '__cpp_structured_bindings' not in macros: if '__cpp_structured_bindings' not in macros:
self.config.available_features.add('libcpp-no-structured-bindings') self.config.available_features.add('libcpp-no-structured-bindings')
if '__cpp_deduction_guides' not in macros:
self.config.available_features.add('libcpp-no-deduction-guides')
if self.is_windows: if self.is_windows:
self.config.available_features.add('windows') self.config.available_features.add('windows')