EricWF created this revision.

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.


https://reviews.llvm.org/D29863

Files:
  include/string
  test/std/strings/basic.string/string.cons/implicit_deduction_guides.pass.cpp

Index: test/std/strings/basic.string/string.cons/implicit_deduction_guides.pass.cpp
===================================================================
--- /dev/null
+++ test/std/strings/basic.string/string.cons/implicit_deduction_guides.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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
+
+// Clang does not implement deduction guides yet.
+// XFAIL: clang, apple-clang
+
+// <string>
+
+// Test that the constructors offered by std::basic_string are formulated
+// so they're compatible with implicit deduction guides.
+
+#include <string>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+
+
+template <class T, class Alloc = std::allocator<T>>
+using BStr = std::basic_string<T, std::char_traits<T>, Alloc>;
+
+
+int main()
+{
+  {
+    std::basic_string s = "hello world";
+    std::basic_string w(L"hello world");
+
+    ASSERT_SAME_TYPE(decltype(s), std::basic_string<char>);
+    ASSERT_SAME_TYPE(decltype(w), std::basic_string<wchar_t>);
+  }
+  {
+    std::basic_string s("hello world", test_allocator<char>{});
+    ASSERT_SAME_TYPE(decltype(s), BStr<char, test_allocator<char>>);
+  }
+  {
+    std::basic_string s("hello world", 2ull, test_allocator<char>{});
+    std::basic_string w(L"hello world", 2ull, test_allocator<wchar_t>{});
+    ASSERT_SAME_TYPE(decltype(s), BStr<char,test_allocator<char>>);
+    ASSERT_SAME_TYPE(decltype(w), BStr<wchar_t, test_allocator<wchar_t>>);
+
+  }
+  {
+    std::string const s1;
+    std::basic_string s(s1);
+    ASSERT_SAME_TYPE(decltype(s), std::string);
+
+    std::basic_string w = std::wstring{};
+    ASSERT_SAME_TYPE(decltype(w), std::wstring);
+  }
+}
Index: include/string
===================================================================
--- include/string
+++ include/string
@@ -775,13 +775,13 @@
     _LIBCPP_INLINE_VISIBILITY
     basic_string(basic_string&& __str, const allocator_type& __a);
 #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
-    basic_string(const value_type* __s, const allocator_type& __a);
+    basic_string(const _CharT* __s, const _Allocator& __a);
     _LIBCPP_INLINE_VISIBILITY
     basic_string(const value_type* __s, size_type __n);
     _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
     basic_string(size_type __n, value_type __c);
     _LIBCPP_INLINE_VISIBILITY
@@ -1557,7 +1557,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 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");
     __init(__s, traits_type::length(__s));
@@ -1568,7 +1568,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 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)
 {
     _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*, allocator) detected nullptr");
@@ -1591,7 +1591,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 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)
 {
     _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to