2

What is the reason that the standard class std::basic_string does not have an "implicit" constructor that accepts as its argument an object of the type std::string_view?

I would expect that this program will compile.

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

struct A
{
    void f( const char *s ) const
    {
        std::cout << "A::f( " << s << " )\n";
    }        
};

struct B
{
    void f( const std::string &s ) const
    {
        std::cout << "B::f( " << s << " )\n";
    }        
};

template <typename... Bases>
struct C : Bases...
{
    using Bases::f...;
};

int main()
{
    C<A, B>().f( std::string_view( "Hello" ) );
    // or
    std::string_view s( "Hello" );
    C<A,B>().f( s );
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • @G.M. Sadly your link just shows all the contructors. Are you referring to the template constructors at the bottom? (10 and 11). They might accept string_view, and indeed they do, but only if you understand "convertable_to" to cover "is". – Gem Taylor Aug 22 '19 at 11:09
  • Actually, string HAS a constructor from string view: [basic_string.h:650](https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/basic_string.h). It has a brief: 'Construct string from a string_view'. So i don't think, this is duplicate – gimme_danger Aug 22 '19 at 11:16

1 Answers1

5

The reason is because many of the string_view accepting functions are ambiguous with the std::string overload of the same function. Take

std::string s({"abc", 1});

for example. This is either create a std::string from a std::string_view by calling the string_view accepting constructor or create a std::string via

basic_string(const CharT* s, size_type count, const Allocator& alloc = Allocator());

LWG 2758 brought this issue up originally and LWG 2946 finished adjusting all of the string_view taking functions to templates. By doing this none of the older string interface needed to be adjusted so older code wont break when compiled under C++17.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • But you could write std::string s( { {"abc", 1 } } ); and there is no ambiguity.:) – Vlad from Moscow Aug 22 '19 at 13:11
  • @VladfromMoscow Would that even work? [It doesn't here](http://coliru.stacked-crooked.com/a/c6c1deac8bcc5d6b) – NathanOliver Aug 22 '19 at 13:14
  • This works. #include #include struct A { A( const char *, size_t ) { std::cout << "A( const char *, size_t )\n"; } A( const std::string_view & ) { std::cout << "A( const std::string_view & )\n"; } }; int main() { A a( { { "abc", 1 } } ); } – Vlad from Moscow Aug 22 '19 at 13:16
  • @VladfromMoscow Ah, nice. That said, having to write `std::string s( { {"abc", 1 } } )` instead of `std::string s({"abc", 1});` makes the language harder for new comers. It violates the principal of least surprise if `std::string s({"abc", 1});` just doesn't work. – NathanOliver Aug 22 '19 at 13:22
  • 2
    The whole point of this hackery is to avoid breaking existing code. It doesn't matter if the existing code can be rewritten in some other way. – T.C. Aug 22 '19 at 13:24