Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructing a std::string_view from a braced std::string, clang and gcc disagree with -Wconversion

GCC 7.2 and clang 5.0 seem to disagree about the following code when compiled with -std=c++17 -Werror -Wconversion:

#include <iostream>
#include <string>
#include <string_view>

int main(int argc, char* argv[]) {
    std::string s = "Hello, World";
    std::string_view vs{s};
    std::cout << std::string{vs} << '\n';
    return EXIT_SUCCESS;
}

Compiled with clang++ -std=c++17 -Wall -Werror -Wconversion, it compiles correctly (see https://godbolt.org/g/JZn8cL)

However, GCC 7.2 issues a somewhat perplexing diagnostic (see https://godbolt.org/g/kmYbJ3):

<source>: In function 'int main(int, char**)':
7 : <source>:7:26: error: choosing 'std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::__sv_type() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::__sv_type = std::basic_string_view<char>]' over 'constexpr std::basic_string_view<_CharT, _Traits>::basic_string_view(const std::basic_string_view<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]' [-Werror=conversion]
     std::string_view vs{s};
                          ^
7 : <source>:7:26: error:   for conversion from 'std::__cxx11::string {aka std::__cxx11::basic_string<char>}' to 'std::basic_string_view<char>' [-Werror=conversion]
7 : <source>:7:26: note:   because conversion sequence for the argument is better
cc1plus: all warnings being treated as errors
Compiler exited with result code 1

Both compilers compile the code fine after changing vs{s} to vs(s).

Which compiler is right here? Is brace initialization of a std::string_view from a std::string running afoul of conversion rules somehow, and clang is failing to issue a diagnostic when it could/should? Or is GCC in the wrong and the diagnostic is erroneous?

like image 363
acm Avatar asked Nov 15 '25 19:11

acm


1 Answers

Which compiler is right here?

Both? Compilers are allowed to give warnings, or not, as they choose. It's just that when you write:

std::string_view vs{s};

You might be under the impression that this is doing something like aggregate initialization or at least invoking a string_view constructor, but it's not - and maybe that impression isn't as likely to happen if you wrote:

std::string_view vs(s);

so gcc gives you a warning (since you asked for one).

The code is fine. Both compilers are fine. Just use ()s to initialize, there's no reason to use {} here (there is no difference in behavior in the two approaches).

like image 52
Barry Avatar answered Nov 18 '25 10:11

Barry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!