https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119748
Bug ID: 119748
Summary: std::string::string(InputIterator, InputIterator)
rejects volatile charT* as iterator
Product: gcc
Version: unknown
Status: UNCONFIRMED
Keywords: rejects-valid
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: redi at gcc dot gnu.org
CC: hewillk at gmail dot com
Target Milestone: ---
#include <string>
volatile char vs[42] = {};
std::string s(std::begin(vs), std::end(vs)); // ?
On trunk this fails because my r15-9381-g648d5c26e25497 assumes that a
contiguous iterator with value_type of char will give us a const char*, but
that's not true for a pointer to volatile char.
With that fixed, it fails for the same reason as GCC 14 and all previous
releases:
include/c++/14.2.1/bits/cow_string.h:426:32: error: binding reference of type
'const std::char_traits<char>::char_type&' {aka 'const char&'} to 'volatile
char' discards qualifiers
426 | traits_type::assign(*__p, *__k1); // These types are off.
| ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
*__k1 gives us volatile char& which cannot bind to const char&
This explains the "These types are off" comment which has been there for
decades!
For X(i, j) the sequence requirements only require that "T is
Cpp17EmplaceConstructible into X from *i" and that means that *i is not
required to be implicitly convertible to the container's value_type, an
explicit conversion might be required.
So the fix is:
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -489,7 +489,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_S_copy(__p, std::__niter_base(__k1), __k2 - __k1);
#if __cpp_lib_concepts
else if constexpr (contiguous_iterator<_Iterator>
- && is_same_v<iter_value_t<_Iterator>, _CharT>)
+ && requires { { std::to_address(__k1) }
+ -> convertible_to<const _CharT*>; })
{
const auto __d = __k2 - __k1;
(void) (__k1 + __d); // See P3349R1
@@ -498,8 +499,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#endif
else
#endif
- for (; __k1 != __k2; ++__k1, (void)++__p)
- traits_type::assign(*__p, *__k1); // These types are off.
+ for (; __k1 != __k2; ++__k1, (void)++__p)
+ traits_type::assign(*__p, static_cast<_CharT>(*__k1));
}
#pragma GCC diagnostic pop