* [v3 PATCH] Implement LWG 2758. @ 2016-08-10 7:50 Ville Voutilainen 2016-08-10 16:06 ` Paolo Carlini 2016-08-16 11:52 ` Jonathan Wakely 0 siblings, 2 replies; 7+ messages in thread From: Ville Voutilainen @ 2016-08-10 7:50 UTC (permalink / raw) To: libstdc++, gcc-patches, Paolo Carlini [-- Attachment #1: Type: text/plain, Size: 667 bytes --] Tested on Linux-x64. 2016-08-10 Ville Voutilainen <ville.voutilainen@gmail.com> Implement LWG 2758. * include/bits/basic_string.h (append(__sv_type, size_type, size_type)): Turn into a template, change parameter type, constrain, add a conversion to __sv_type from the dependent parameter type. (assign(__sv_type, size_type, size_type)): Likewise. (insert(size_type, __sv_type, size_type, size_type)): Likewise. (replace(size_type, size_type, __sv_type, size_type, size_type)): Likewise. (compare(size_type, size_type,__sv_type, size_type, size_type)): Likewise. * testsuite/21_strings/basic_string/lwg2758.cc: New. [-- Attachment #2: lwg2758.diff --] [-- Type: text/plain, Size: 4900 bytes --] diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 59f1c64..89e2100 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -1227,9 +1227,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to append from the string_view. * @return Reference to this string. */ - basic_string& append(__sv_type __sv, + template <typename _Tp, + enable_if_t<is_convertible_v<const _Tp&, __sv_type>, + bool> = true> + basic_string& append(const _Tp& __svt, size_type __pos, size_type __n = npos) { + __sv_type __sv = __svt; return _M_append(__sv.data() + __sv._M_check(__pos, "basic_string::append"), __sv._M_limit(__pos, __n)); @@ -1392,10 +1396,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to assign. * @return Reference to this string. */ + template <typename _Tp, + enable_if_t<is_convertible_v<const _Tp&, __sv_type>, + bool> = true> basic_string& - assign(__sv_type __sv, + assign(const _Tp& __svt, size_type __pos, size_type __n = npos) { + __sv_type __sv = __svt; return _M_replace(size_type(0), this->size(), __sv.data() + __sv._M_check(__pos, "basic_string::assign"), __sv._M_limit(__pos, __n)); @@ -1652,9 +1660,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to insert. * @return Reference to this string. */ - basic_string& insert(size_type __pos1, __sv_type __sv, + template <typename _Tp, + enable_if_t<is_convertible_v<const _Tp&, __sv_type>, + bool> = true> + basic_string& insert(size_type __pos1, const _Tp& __svt, size_type __pos2, size_type __n = npos) { + __sv_type __sv = __svt; return this->replace(__pos1, size_type(0), __sv.data() + __sv._M_check(__pos2, "basic_string::insert"), __sv._M_limit(__pos2, __n)); @@ -2071,10 +2083,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n2 The number of characters to insert. * @return Reference to this string. */ + template <typename _Tp, + enable_if_t<is_convertible_v<const _Tp&, __sv_type>, + bool> = true> basic_string& replace(size_type __pos1, size_type __n1, - __sv_type __sv, + const _Tp& __svt, size_type __pos2, size_type __n2 = npos) { + __sv_type __sv = __svt; return this->replace(__pos1, __n1, __sv.data() + __sv._M_check(__pos2, "basic_string::replace"), __sv._M_limit(__pos2, __n2)); @@ -2720,10 +2736,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n2 The number of characters to compare. * @return Integer < 0, 0, or > 0. */ + template <typename _Tp, + enable_if_t<is_convertible_v<const _Tp&, __sv_type>, + bool> = true> int compare(size_type __pos1, size_type __n1, - __sv_type __sv, + const _Tp& __svt, size_type __pos2, size_type __n2 = npos) const { + __sv_type __sv = __svt; return __sv_type(*this) .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc new file mode 100644 index 0000000..1d29248 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc @@ -0,0 +1,46 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <string> + +struct CustomString +{ + std::string data = "foo"; + std::string_view data_view = data; + operator std::string_view() const {return data_view;} +}; + +int main() +{ + std::string x; + CustomString cs; + x.append("foo", 0, 3); + x.append(cs, 0, 3); + x.assign("foo", 0, 3); + x.assign(cs, 0, 3); + x.insert(0, "foo", 0, 3); + x.insert(0, cs, 0, 3); + x = "bar"; + x.replace(0, 3, "foo", 0, 3); + x.replace(0, 3, cs, 0, 3); + x = "bar"; + x.compare(0, 3, "foo", 0, 3); + x.compare(0, 3, cs, 0, 3); +} ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [v3 PATCH] Implement LWG 2758. 2016-08-10 7:50 [v3 PATCH] Implement LWG 2758 Ville Voutilainen @ 2016-08-10 16:06 ` Paolo Carlini 2016-08-10 16:50 ` Ville Voutilainen 2016-08-16 11:52 ` Jonathan Wakely 1 sibling, 1 reply; 7+ messages in thread From: Paolo Carlini @ 2016-08-10 16:06 UTC (permalink / raw) To: Ville Voutilainen, libstdc++, gcc-patches Hi Ville, On 10/08/2016 09:50, Ville Voutilainen wrote: > Tested on Linux-x64. > > 2016-08-10 Ville Voutilainen <ville.voutilainen@gmail.com> > > Implement LWG 2758. If I understand correctly this touches only the new C++17 members and in any case, a recent commit by Jon disabled the extern template strings in C++17 mode, thus there are no ABI-related risks in that mode. Patch looks good to me. I'll get to your other contributions later today. Thanks, Paolo. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [v3 PATCH] Implement LWG 2758. 2016-08-10 16:06 ` Paolo Carlini @ 2016-08-10 16:50 ` Ville Voutilainen 0 siblings, 0 replies; 7+ messages in thread From: Ville Voutilainen @ 2016-08-10 16:50 UTC (permalink / raw) To: Paolo Carlini; +Cc: libstdc++, gcc-patches On 10 August 2016 at 19:06, Paolo Carlini <paolo.carlini@oracle.com> wrote: >> Implement LWG 2758. > > If I understand correctly this touches only the new C++17 members and in any > case, a recent commit by Jon disabled the extern template strings in C++17 > mode, thus there are no ABI-related risks in that mode. Correct, afaik. > Patch looks good to me. I'll get to your other contributions later today. Thanks, I will commit this patch later today. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [v3 PATCH] Implement LWG 2758. 2016-08-10 7:50 [v3 PATCH] Implement LWG 2758 Ville Voutilainen 2016-08-10 16:06 ` Paolo Carlini @ 2016-08-16 11:52 ` Jonathan Wakely 2016-08-16 12:58 ` Jonathan Wakely 1 sibling, 1 reply; 7+ messages in thread From: Jonathan Wakely @ 2016-08-16 11:52 UTC (permalink / raw) To: Ville Voutilainen; +Cc: libstdc++, gcc-patches, Paolo Carlini On 10/08/16 10:50 +0300, Ville Voutilainen wrote: >diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h >index 59f1c64..89e2100 100644 >--- a/libstdc++-v3/include/bits/basic_string.h >+++ b/libstdc++-v3/include/bits/basic_string.h >@@ -1227,9 +1227,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 > * @param __n The number of characters to append from the string_view. > * @return Reference to this string. > */ >- basic_string& append(__sv_type __sv, >+ template <typename _Tp, >+ enable_if_t<is_convertible_v<const _Tp&, __sv_type>, >+ bool> = true> >+ basic_string& append(const _Tp& __svt, > size_type __pos, size_type __n = npos) I would prefer the enable_if constraint to be on the return type, so there is only one template parameter: template <typename _Tp> enable_if_t<is_convertible_v<const _Tp&, __sv_type>, basic_string&> append(const _Tp& __svt, size_type __pos, size_type __n = npos) However these function templates appear to have a design problem, see PR 77264. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [v3 PATCH] Implement LWG 2758. 2016-08-16 11:52 ` Jonathan Wakely @ 2016-08-16 12:58 ` Jonathan Wakely 2016-08-16 13:15 ` Ville Voutilainen 0 siblings, 1 reply; 7+ messages in thread From: Jonathan Wakely @ 2016-08-16 12:58 UTC (permalink / raw) To: Ville Voutilainen; +Cc: libstdc++, gcc-patches, Paolo Carlini [-- Attachment #1: Type: text/plain, Size: 1642 bytes --] On 16/08/16 12:52 +0100, Jonathan Wakely wrote: >On 10/08/16 10:50 +0300, Ville Voutilainen wrote: >>diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h >>index 59f1c64..89e2100 100644 >>--- a/libstdc++-v3/include/bits/basic_string.h >>+++ b/libstdc++-v3/include/bits/basic_string.h >>@@ -1227,9 +1227,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> * @param __n The number of characters to append from the string_view. >> * @return Reference to this string. >> */ >>- basic_string& append(__sv_type __sv, >>+ template <typename _Tp, >>+ enable_if_t<is_convertible_v<const _Tp&, __sv_type>, >>+ bool> = true> >>+ basic_string& append(const _Tp& __svt, >> size_type __pos, size_type __n = npos) > >I would prefer the enable_if constraint to be on the return type, so >there is only one template parameter: > > template <typename _Tp> > enable_if_t<is_convertible_v<const _Tp&, __sv_type>, basic_string&> > append(const _Tp& __svt, > size_type __pos, size_type __n = npos) > >However these function templates appear to have a design problem, see >PR 77264. This patch constrains the new overloads using: template<typename _Tp, typename _Res> using _If_sv = enable_if_t< __and_<is_convertible<const _Tp&, __sv_type>, __not_<is_convertible<const _Tp&, const _CharT*>>>::value, _Res>; so that anything convertible to const _CharT* goes to the same overload as would have been chosen prior to C++17. I'm testing this now but won't commit it until it's clear this is a sensible resolution for LWG 2758. [-- Attachment #2: patch.txt --] [-- Type: text/x-patch, Size: 11428 bytes --] commit 80e14013c4581fba08099f7a627c63cebc2a378e Author: Jonathan Wakely <jwakely@redhat.com> Date: Tue Aug 16 13:50:55 2016 +0100 PR 77264 constrain new std::basic_string overloads PR libstdc++/77264 * include/bits/basic_string.h (operator=(__sv_type) (append(__sv_type), assign(__sv_type), insert(size_type, __sv_type)) (replace(size_type, size_type, __sv_type)) (replace(const_iterator, const_iterator, __sv_type)) (find(__sv_type, size_type), rfind(__sv_type, size_type)) (compare(size_type, size_type, __sv_type)): Reformat. (_If_sv): Define helper for SFINAE constaints. (append(const _Tp&, size_type, size_type)) (assign(const _Tp&, size_type, size_type)) (insert(size_type, const _Tp&, size_type, size_type)) (replace(size_type, size_type, const _Tp&, size_type, size_type)): Use _If_sv. * testsuite/21_strings/basic_string/modifiers/replace/char/7.cc: Test SFINAE constraints. * testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc: Likewise. diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 89e2100..68cfc99 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -709,7 +709,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Set value to string constructed from a string_view. * @param __sv A string_view. */ - basic_string& operator=(__sv_type __sv) + basic_string& + operator=(__sv_type __sv) { return this->assign(__sv); } /** @@ -1217,9 +1218,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to be appended. * @return Reference to this string. */ - basic_string& append(__sv_type __sv) + basic_string& + append(__sv_type __sv) { return this->append(__sv.data(), __sv.size()); } + template<typename _Tp, typename _Res> + using _If_sv = enable_if_t< + __and_<is_convertible<const _Tp&, __sv_type>, + __not_<is_convertible<const _Tp&, const _CharT*>>>::value, + _Res>; + /** * @brief Append a range of characters from a string_view. * @param __sv The string_view to be appended from. @@ -1227,17 +1235,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to append from the string_view. * @return Reference to this string. */ - template <typename _Tp, - enable_if_t<is_convertible_v<const _Tp&, __sv_type>, - bool> = true> - basic_string& append(const _Tp& __svt, - size_type __pos, size_type __n = npos) - { - __sv_type __sv = __svt; - return _M_append(__sv.data() - + __sv._M_check(__pos, "basic_string::append"), - __sv._M_limit(__pos, __n)); - } + template <typename _Tp> + _If_sv<_Tp, basic_string&> + append(const _Tp& __svt, size_type __pos, size_type __n = npos) + { + __sv_type __sv = __svt; + return _M_append(__sv.data() + + __sv._M_check(__pos, "basic_string::append"), + __sv._M_limit(__pos, __n)); + } #endif // C++17 /** @@ -1386,7 +1392,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The source string_view. * @return Reference to this string. */ - basic_string& assign(__sv_type __sv) + basic_string& + assign(__sv_type __sv) { return this->assign(__sv.data(), __sv.size()); } /** @@ -1396,18 +1403,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to assign. * @return Reference to this string. */ - template <typename _Tp, - enable_if_t<is_convertible_v<const _Tp&, __sv_type>, - bool> = true> - basic_string& - assign(const _Tp& __svt, - size_type __pos, size_type __n = npos) - { - __sv_type __sv = __svt; - return _M_replace(size_type(0), this->size(), __sv.data() - + __sv._M_check(__pos, "basic_string::assign"), - __sv._M_limit(__pos, __n)); - } + template <typename _Tp> + _If_sv<_Tp, basic_string&> + assign(const _Tp& __svt, size_type __pos, size_type __n = npos) + { + __sv_type __sv = __svt; + return _M_replace(size_type(0), this->size(), __sv.data() + + __sv._M_check(__pos, "basic_string::assign"), + __sv._M_limit(__pos, __n)); + } #endif // C++17 #if __cplusplus >= 201103L @@ -1647,8 +1651,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert. * @return Reference to this string. */ - basic_string& insert(size_type __pos, - __sv_type __sv) + basic_string& + insert(size_type __pos, __sv_type __sv) { return this->insert(__pos, __sv.data(), __sv.size()); } /** @@ -1660,17 +1664,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to insert. * @return Reference to this string. */ - template <typename _Tp, - enable_if_t<is_convertible_v<const _Tp&, __sv_type>, - bool> = true> - basic_string& insert(size_type __pos1, const _Tp& __svt, - size_type __pos2, size_type __n = npos) - { - __sv_type __sv = __svt; - return this->replace(__pos1, size_type(0), __sv.data() - + __sv._M_check(__pos2, "basic_string::insert"), - __sv._M_limit(__pos2, __n)); - } + template <typename _Tp> + _If_sv<_Tp, basic_string&> + insert(size_type __pos1, const _Tp& __svt, + size_type __pos2, size_type __n = npos) + { + __sv_type __sv = __svt; + return this->replace(__pos1, size_type(0), __sv.data() + + __sv._M_check(__pos2, "basic_string::insert"), + __sv._M_limit(__pos2, __n)); + } #endif // C++17 /** @@ -2070,8 +2073,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert. * @return Reference to this string. */ - basic_string& replace(size_type __pos, size_type __n, - __sv_type __sv) + basic_string& + replace(size_type __pos, size_type __n, __sv_type __sv) { return this->replace(__pos, __n, __sv.data(), __sv.size()); } /** @@ -2083,18 +2086,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n2 The number of characters to insert. * @return Reference to this string. */ - template <typename _Tp, - enable_if_t<is_convertible_v<const _Tp&, __sv_type>, - bool> = true> - basic_string& replace(size_type __pos1, size_type __n1, - const _Tp& __svt, - size_type __pos2, size_type __n2 = npos) - { - __sv_type __sv = __svt; - return this->replace(__pos1, __n1, __sv.data() - + __sv._M_check(__pos2, "basic_string::replace"), - __sv._M_limit(__pos2, __n2)); - } + template <typename _Tp> + _If_sv<_Tp, basic_string&> + replace(size_type __pos1, size_type __n1, const _Tp& __svt, + size_type __pos2, size_type __n2 = npos) + { + __sv_type __sv = __svt; + return this->replace(__pos1, __n1, __sv.data() + + __sv._M_check(__pos2, "basic_string::replace"), + __sv._M_limit(__pos2, __n2)); + } /** * @brief Replace range of characters with string_view. @@ -2105,8 +2106,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert from. * @return Reference to this string. */ - basic_string& replace(const_iterator __i1, const_iterator __i2, - __sv_type __sv) + basic_string& + replace(const_iterator __i1, const_iterator __i2, __sv_type __sv) { return this->replace(__i1 - begin(), __i2 - __i1, __sv); } #endif // C++17 @@ -2241,8 +2242,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of first occurrence. */ size_type - find(__sv_type __sv, - size_type __pos = 0) const noexcept + find(__sv_type __sv, size_type __pos = 0) const noexcept { return this->find(__sv.data(), __pos, __sv.size()); } #endif // C++17 @@ -2299,8 +2299,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of last occurrence. */ size_type - rfind (__sv_type __sv, - size_type __pos = npos) const noexcept + rfind(__sv_type __sv, size_type __pos = npos) const noexcept { return this->rfind(__sv.data(), __pos, __sv.size()); } #endif // C++17 @@ -2721,11 +2720,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ int - compare(size_type __pos, size_type __n, - __sv_type __sv) const - { - return __sv_type(*this).substr(__pos, __n).compare(__sv); - } + compare(size_type __pos, size_type __n, __sv_type __sv) const + { return __sv_type(*this).substr(__pos, __n).compare(__sv); } /** * @brief Compare to a string_view. @@ -2736,17 +2732,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n2 The number of characters to compare. * @return Integer < 0, 0, or > 0. */ - template <typename _Tp, - enable_if_t<is_convertible_v<const _Tp&, __sv_type>, - bool> = true> - int compare(size_type __pos1, size_type __n1, - const _Tp& __svt, - size_type __pos2, size_type __n2 = npos) const - { - __sv_type __sv = __svt; - return __sv_type(*this) - .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); - } + template <typename _Tp> + _If_sv<_Tp, int> + compare(size_type __pos1, size_type __n1, const _Tp& __svt, + size_type __pos2, size_type __n2 = npos) const + { + __sv_type __sv = __svt; + return __sv_type(*this) + .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); + } #endif // C++17 /** diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc index 004b235..2a2858b 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc @@ -47,8 +47,30 @@ test03() VERIFY (str2 == "foofoo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::string str("a"); + char c = 'b'; + str.replace(0, 1, &c, 1); + VERIFY (str[0] == 'b'); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'a'; + }; + + str.replace(0, 1, S{}, 1); + VERIFY (str[0] == 'a'); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc index 88d2666..1e2505e 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc @@ -47,8 +47,30 @@ test03() VERIFY (str2 == L"foofoo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::wstring str(L"a"); + wchar_t c = L'b'; + str.replace(0, 1, &c, 1); + VERIFY (str[0] == L'b'); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'a'; + }; + + str.replace(0, 1, S{}, 1); + VERIFY (str[0] == L'a'); +} + int main() { test03(); + test04(); return 0; } ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [v3 PATCH] Implement LWG 2758. 2016-08-16 12:58 ` Jonathan Wakely @ 2016-08-16 13:15 ` Ville Voutilainen 2016-08-17 13:41 ` Jonathan Wakely 0 siblings, 1 reply; 7+ messages in thread From: Ville Voutilainen @ 2016-08-16 13:15 UTC (permalink / raw) To: Jonathan Wakely; +Cc: libstdc++, gcc-patches, Paolo Carlini On 16 August 2016 at 15:58, Jonathan Wakely <jwakely@redhat.com> wrote: > This patch constrains the new overloads using: > > template<typename _Tp, typename _Res> > using _If_sv = enable_if_t< > __and_<is_convertible<const _Tp&, __sv_type>, > __not_<is_convertible<const _Tp&, const _CharT*>>>::value, > _Res>; > > so that anything convertible to const _CharT* goes to the same > overload as would have been chosen prior to C++17. > > I'm testing this now but won't commit it until it's clear this is a > sensible resolution for LWG 2758. It's crystal clear to me that it is, ship it. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [v3 PATCH] Implement LWG 2758. 2016-08-16 13:15 ` Ville Voutilainen @ 2016-08-17 13:41 ` Jonathan Wakely 0 siblings, 0 replies; 7+ messages in thread From: Jonathan Wakely @ 2016-08-17 13:41 UTC (permalink / raw) To: Ville Voutilainen; +Cc: libstdc++, gcc-patches, Paolo Carlini [-- Attachment #1: Type: text/plain, Size: 797 bytes --] On 16/08/16 16:15 +0300, Ville Voutilainen wrote: >On 16 August 2016 at 15:58, Jonathan Wakely <jwakely@redhat.com> wrote: >> This patch constrains the new overloads using: >> >> template<typename _Tp, typename _Res> >> using _If_sv = enable_if_t< >> __and_<is_convertible<const _Tp&, __sv_type>, >> __not_<is_convertible<const _Tp&, const _CharT*>>>::value, >> _Res>; >> >> so that anything convertible to const _CharT* goes to the same >> overload as would have been chosen prior to C++17. >> >> I'm testing this now but won't commit it until it's clear this is a >> sensible resolution for LWG 2758. > > >It's crystal clear to me that it is, ship it. Here's what I've committed, adding tests for the other functions too. Tested ppx64le-linux, committed to trunk. [-- Attachment #2: patch.txt --] [-- Type: text/x-patch, Size: 20762 bytes --] commit 23d36bb4513f6917f55729080e03f3d69f558acf Author: Jonathan Wakely <jwakely@redhat.com> Date: Tue Aug 16 13:50:55 2016 +0100 PR 77264 constrain new std::basic_string overloads PR libstdc++/77264 * include/bits/basic_string.h (operator=(__sv_type) (append(__sv_type), assign(__sv_type), insert(size_type, __sv_type)) (replace(size_type, size_type, __sv_type)) (replace(const_iterator, const_iterator, __sv_type)) (find(__sv_type, size_type), rfind(__sv_type, size_type)) (compare(size_type, size_type, __sv_type)): Reformat. (_If_sv): Define helper for SFINAE constaints. (append(const _Tp&, size_type, size_type)) (assign(const _Tp&, size_type, size_type)) (insert(size_type, const _Tp&, size_type, size_type)) (replace(size_type, size_type, const _Tp&, size_type, size_type)): Use _If_sv. * testsuite/21_strings/basic_string/modifiers/append/char/4.cc: Test SFINAE constraints. * testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/replace/char/7.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/assign/char/4.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/assign/wchar_t/4.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/insert/char/3.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc: Likewise. * testsuite/21_strings/basic_string/modifiers/replace/char/7.cc: Likewise. * testsuite/21_strings/basic_string/operations/compare/char/2.cc: Likewise. * testsuite/21_strings/basic_string/operations/compare/wchar_t/2.cc: Likewise. diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 89e2100..68cfc99 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -709,7 +709,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Set value to string constructed from a string_view. * @param __sv A string_view. */ - basic_string& operator=(__sv_type __sv) + basic_string& + operator=(__sv_type __sv) { return this->assign(__sv); } /** @@ -1217,9 +1218,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to be appended. * @return Reference to this string. */ - basic_string& append(__sv_type __sv) + basic_string& + append(__sv_type __sv) { return this->append(__sv.data(), __sv.size()); } + template<typename _Tp, typename _Res> + using _If_sv = enable_if_t< + __and_<is_convertible<const _Tp&, __sv_type>, + __not_<is_convertible<const _Tp&, const _CharT*>>>::value, + _Res>; + /** * @brief Append a range of characters from a string_view. * @param __sv The string_view to be appended from. @@ -1227,17 +1235,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to append from the string_view. * @return Reference to this string. */ - template <typename _Tp, - enable_if_t<is_convertible_v<const _Tp&, __sv_type>, - bool> = true> - basic_string& append(const _Tp& __svt, - size_type __pos, size_type __n = npos) - { - __sv_type __sv = __svt; - return _M_append(__sv.data() - + __sv._M_check(__pos, "basic_string::append"), - __sv._M_limit(__pos, __n)); - } + template <typename _Tp> + _If_sv<_Tp, basic_string&> + append(const _Tp& __svt, size_type __pos, size_type __n = npos) + { + __sv_type __sv = __svt; + return _M_append(__sv.data() + + __sv._M_check(__pos, "basic_string::append"), + __sv._M_limit(__pos, __n)); + } #endif // C++17 /** @@ -1386,7 +1392,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The source string_view. * @return Reference to this string. */ - basic_string& assign(__sv_type __sv) + basic_string& + assign(__sv_type __sv) { return this->assign(__sv.data(), __sv.size()); } /** @@ -1396,18 +1403,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to assign. * @return Reference to this string. */ - template <typename _Tp, - enable_if_t<is_convertible_v<const _Tp&, __sv_type>, - bool> = true> - basic_string& - assign(const _Tp& __svt, - size_type __pos, size_type __n = npos) - { - __sv_type __sv = __svt; - return _M_replace(size_type(0), this->size(), __sv.data() - + __sv._M_check(__pos, "basic_string::assign"), - __sv._M_limit(__pos, __n)); - } + template <typename _Tp> + _If_sv<_Tp, basic_string&> + assign(const _Tp& __svt, size_type __pos, size_type __n = npos) + { + __sv_type __sv = __svt; + return _M_replace(size_type(0), this->size(), __sv.data() + + __sv._M_check(__pos, "basic_string::assign"), + __sv._M_limit(__pos, __n)); + } #endif // C++17 #if __cplusplus >= 201103L @@ -1647,8 +1651,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert. * @return Reference to this string. */ - basic_string& insert(size_type __pos, - __sv_type __sv) + basic_string& + insert(size_type __pos, __sv_type __sv) { return this->insert(__pos, __sv.data(), __sv.size()); } /** @@ -1660,17 +1664,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to insert. * @return Reference to this string. */ - template <typename _Tp, - enable_if_t<is_convertible_v<const _Tp&, __sv_type>, - bool> = true> - basic_string& insert(size_type __pos1, const _Tp& __svt, - size_type __pos2, size_type __n = npos) - { - __sv_type __sv = __svt; - return this->replace(__pos1, size_type(0), __sv.data() - + __sv._M_check(__pos2, "basic_string::insert"), - __sv._M_limit(__pos2, __n)); - } + template <typename _Tp> + _If_sv<_Tp, basic_string&> + insert(size_type __pos1, const _Tp& __svt, + size_type __pos2, size_type __n = npos) + { + __sv_type __sv = __svt; + return this->replace(__pos1, size_type(0), __sv.data() + + __sv._M_check(__pos2, "basic_string::insert"), + __sv._M_limit(__pos2, __n)); + } #endif // C++17 /** @@ -2070,8 +2073,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert. * @return Reference to this string. */ - basic_string& replace(size_type __pos, size_type __n, - __sv_type __sv) + basic_string& + replace(size_type __pos, size_type __n, __sv_type __sv) { return this->replace(__pos, __n, __sv.data(), __sv.size()); } /** @@ -2083,18 +2086,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n2 The number of characters to insert. * @return Reference to this string. */ - template <typename _Tp, - enable_if_t<is_convertible_v<const _Tp&, __sv_type>, - bool> = true> - basic_string& replace(size_type __pos1, size_type __n1, - const _Tp& __svt, - size_type __pos2, size_type __n2 = npos) - { - __sv_type __sv = __svt; - return this->replace(__pos1, __n1, __sv.data() - + __sv._M_check(__pos2, "basic_string::replace"), - __sv._M_limit(__pos2, __n2)); - } + template <typename _Tp> + _If_sv<_Tp, basic_string&> + replace(size_type __pos1, size_type __n1, const _Tp& __svt, + size_type __pos2, size_type __n2 = npos) + { + __sv_type __sv = __svt; + return this->replace(__pos1, __n1, __sv.data() + + __sv._M_check(__pos2, "basic_string::replace"), + __sv._M_limit(__pos2, __n2)); + } /** * @brief Replace range of characters with string_view. @@ -2105,8 +2106,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert from. * @return Reference to this string. */ - basic_string& replace(const_iterator __i1, const_iterator __i2, - __sv_type __sv) + basic_string& + replace(const_iterator __i1, const_iterator __i2, __sv_type __sv) { return this->replace(__i1 - begin(), __i2 - __i1, __sv); } #endif // C++17 @@ -2241,8 +2242,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of first occurrence. */ size_type - find(__sv_type __sv, - size_type __pos = 0) const noexcept + find(__sv_type __sv, size_type __pos = 0) const noexcept { return this->find(__sv.data(), __pos, __sv.size()); } #endif // C++17 @@ -2299,8 +2299,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of last occurrence. */ size_type - rfind (__sv_type __sv, - size_type __pos = npos) const noexcept + rfind(__sv_type __sv, size_type __pos = npos) const noexcept { return this->rfind(__sv.data(), __pos, __sv.size()); } #endif // C++17 @@ -2721,11 +2720,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ int - compare(size_type __pos, size_type __n, - __sv_type __sv) const - { - return __sv_type(*this).substr(__pos, __n).compare(__sv); - } + compare(size_type __pos, size_type __n, __sv_type __sv) const + { return __sv_type(*this).substr(__pos, __n).compare(__sv); } /** * @brief Compare to a string_view. @@ -2736,17 +2732,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n2 The number of characters to compare. * @return Integer < 0, 0, or > 0. */ - template <typename _Tp, - enable_if_t<is_convertible_v<const _Tp&, __sv_type>, - bool> = true> - int compare(size_type __pos1, size_type __n1, - const _Tp& __svt, - size_type __pos2, size_type __n2 = npos) const - { - __sv_type __sv = __svt; - return __sv_type(*this) - .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); - } + template <typename _Tp> + _If_sv<_Tp, int> + compare(size_type __pos1, size_type __n1, const _Tp& __svt, + size_type __pos2, size_type __n2 = npos) const + { + __sv_type __sv = __svt; + return __sv_type(*this) + .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); + } #endif // C++17 /** diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/4.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/4.cc index 2a94452..0df4a6d 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/4.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/4.cc @@ -38,8 +38,38 @@ test03() VERIFY (str4 == "oo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::string str("a"); + char c = 'b'; + str.append(&c, 1); + VERIFY (str[1] == c); + + char arr[] = "c"; + str.append(arr, 1); + VERIFY (str[2] == arr[0]); + + const char carr[] = "d"; + str.append(carr, 1); + VERIFY (str[3] == carr[0]); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'e'; + }; + + str.append(S{}, 1); + VERIFY (str[4] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc index 5512f06..dc1bd64 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc @@ -38,8 +38,39 @@ test03() VERIFY (str4 == L"oo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::wstring str(L"a"); + + wchar_t c = L'b'; + str.append(&c, 1); + VERIFY (str[1] == c); + + wchar_t arr[] = L"c"; + str.append(arr, 1); + VERIFY (str[2] == arr[0]); + + const wchar_t carr[] = L"d"; + str.append(carr, 1); + VERIFY (str[3] == carr[0]); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'e'; + }; + + str.append(S{}, 1); + VERIFY (str[4] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/4.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/4.cc index b8955b5..201dee0 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/4.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/4.cc @@ -35,8 +35,38 @@ test03() VERIFY (str4 == "oo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::string str("a"); + char c = 'b'; + str.assign(&c, 1); + VERIFY (str[0] == c); + + char arr[] = "c"; + str.assign(arr, 1); + VERIFY (str[0] == arr[0]); + + const char carr[] = "d"; + str.assign(carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'e'; + }; + + str.assign(S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/4.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/4.cc index bde158f..5fb7a64 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/4.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/4.cc @@ -35,8 +35,39 @@ test03() VERIFY (str4 == L"oo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::wstring str(L"a"); + + wchar_t c = L'b'; + str.assign(&c, 1); + VERIFY (str[0] == c); + + wchar_t arr[] = L"c"; + str.assign(arr, 1); + VERIFY (str[0] == arr[0]); + + const wchar_t carr[] = L"d"; + str.assign(carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'e'; + }; + + str.assign(S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/3.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/3.cc index 71e5165..7ebbb33 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/3.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/3.cc @@ -39,8 +39,38 @@ test03() VERIFY (str4 == "foooooo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::string str("a"); + char c = 'b'; + str.insert(0, &c, 1); + VERIFY (str[0] == c); + + char arr[] = "c"; + str.insert(0, arr, 1); + VERIFY (str[0] == arr[0]); + + const char carr[] = "d"; + str.insert(0, carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'e'; + }; + + str.insert(0, S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc index 6cddcbe..5d2587c 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc @@ -39,8 +39,39 @@ test03() VERIFY (str4 == L"foooooo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::wstring str(L"a"); + + wchar_t c = L'b'; + str.insert(0, &c, 1); + VERIFY (str[0] == c); + + wchar_t arr[] = L"c"; + str.insert(0, arr, 1); + VERIFY (str[0] == arr[0]); + + const wchar_t carr[] = L"d"; + str.insert(0, carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'e'; + }; + + str.insert(0, S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc index 004b235..afefa84 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc @@ -47,8 +47,38 @@ test03() VERIFY (str2 == "foofoo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::string str("a"); + char c = 'b'; + str.replace(0, 1, &c, 1); + VERIFY (str[0] == c); + + char arr[] = "c"; + str.replace(0, 1, arr, 1); + VERIFY (str[0] == arr[0]); + + const char carr[] = "d"; + str.replace(0, 1, carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'e'; + }; + + str.replace(0, 1, S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc index 88d2666..692c52d 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc @@ -47,8 +47,39 @@ test03() VERIFY (str2 == L"foofoo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::wstring str(L"a"); + + wchar_t c = L'b'; + str.replace(0, 1, &c, 1); + VERIFY (str[0] == c); + + wchar_t arr[] = L"c"; + str.replace(0, 1, arr, 1); + VERIFY (str[0] == arr[0]); + + const wchar_t carr[] = L"d"; + str.replace(0, 1, carr, 1); + VERIFY (str[0] == carr[0]); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'e'; + }; + + str.replace(0, 1, S{}, 1); + VERIFY (str[0] == S{}.c); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/char/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/char/2.cc index 65474d0..08b3f0c 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/char/2.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/char/2.cc @@ -49,8 +49,38 @@ test03() VERIFY (x == 0); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + const std::string str("a"); + char c = 'a'; + int res = str.compare(0, 1, &c, 1); + VERIFY ( !res ); + + char arr[] = "a"; + res = str.compare(0, 1, arr, 1); + VERIFY ( !res ); + + const char carr[] = "a"; + res = str.compare(0, 1, carr, 1); + VERIFY ( !res ); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'a'; + }; + + res = str.compare(0, 1, S{}, 1); + VERIFY ( !res ); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/wchar_t/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/wchar_t/2.cc index f7a9760..d79dcd5 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/wchar_t/2.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/wchar_t/2.cc @@ -49,8 +49,39 @@ test03() VERIFY (x == 0); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + const std::wstring str(L"a"); + + wchar_t c = L'a'; + int res = str.compare(0, 1, &c, 1); + VERIFY ( !res ); + + wchar_t arr[] = L"a"; + res = str.compare(0, 1, arr, 1); + VERIFY ( !res ); + + const wchar_t carr[] = L"a"; + res = str.compare(0, 1, carr, 1); + VERIFY ( !res ); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'a'; + }; + + res = str.compare(0, 1, S{}, 1); + VERIFY ( !res ); +} + int main() { test03(); + test04(); return 0; } ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2016-08-17 13:41 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-08-10 7:50 [v3 PATCH] Implement LWG 2758 Ville Voutilainen 2016-08-10 16:06 ` Paolo Carlini 2016-08-10 16:50 ` Ville Voutilainen 2016-08-16 11:52 ` Jonathan Wakely 2016-08-16 12:58 ` Jonathan Wakely 2016-08-16 13:15 ` Ville Voutilainen 2016-08-17 13:41 ` Jonathan Wakely
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).