Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #85789

Re: map[string_view] not compiling

From "Alf P. Steinbach" <alf.p.steinbach@gmail.com>
Newsgroups comp.lang.c++
Subject Re: map[string_view] not compiling
Date 2022-08-03 11:34 +0200
Organization A noiseless patient Spider
Message-ID <tcdff0$25305$1@dont-email.me> (permalink)
References <tc8epl$t0hn$1@dont-email.me>

Show all headers | View raw


On 1 Aug 2022 13:52, Paavo Helde wrote:
> 
> Hi all,
> 
> Let's say I have a std::map with std::string keys and want to access it 
> with std::string_view keys. For lookup there is a trick to add 
> std::less<> to the map definition, but it appears this does not help 
> with operator[] by some reason. Maybe some expert can clarify this?
> 
> Here is an example:
> 
> #include <map>
> #include <string>
> using namespace std::string_view_literals;
> 
> 
> int main() {
> 
>      std::string_view key = "foo"sv;
> 
>      std::map<std::string, int> a;
>      //auto it = a.find(key); // not compiling
>      // cannot convert argument 1 from 'std::string_view' to 'const 
> std::basic_string ...
> 
>      std::map<std::string, int, std::less<>> b;
>      auto it = b.find(key); // OK now
> 
>      b[key] = 3; // still not compiling
>      //  binary '[': no operator found which takes a right-hand operand 
> of type 'std::string_view'
> 
>      b[std::string(key)] = 3; // OK now, but may construct a std::string 
> without reason
> 
> }

`map::operator[]` may create a new `string` -> `int` mapping. But it 
doesn't know how to create a `string` key from a `string_view` 
key-comparable. Or from say a `double` key comparable, if one defined 
such comparison (simply casting to `string` wouldn't even compile).

You may use code like the following, which I believe both clarifies the 
issues and is one practical solution.

I chose to also address the silly `no operator[] for const` issue, but 
this just-cobbled-together code lacks support for custom comparators.


#include <functional>
#include <map>
#include <stdexcept>
#include <string>
#include <string_view>
#include <utility>
using namespace std::literals;

namespace my {
     using   std::less,
             std::map,
             std::out_of_range,
             std::string,
             std::string_view,
             std::forward;

     template< class Key >
     struct Default_key_factory_
     {
         template< class Key_id >
         static auto make_key( Key_id&& key_id )
             -> Key
         { return Key( forward<Key_id>( key_id ) ); }
     };

     template< class Key_, class Item_, class Key_factory_ = 
Default_key_factory_<Key_> >
     class Map_:
         private map<Key_, Item_, less<>>
     {
     public:
         using Key           = Key_;
         using Key_factory   = Key_factory_;
         using Item          = Item_;

         using Self      = Map_;
         using Std_map   = map<Key, Item, less<>>;

         using Std_map::Std_map;
         using Std_map::find;
         using Std_map::count;
         using Std_map::lower_bound;
         using Std_map::upper_bound;
         using Std_map::equal_range;

         template< class Key_id >
         auto forced_item( const Key_id& key_id )
             -> Item&
         {
             const auto it = Self::find( key_id );
             if( it == Self::end() ) {
                 return Std_map::operator[]( Key_factory::make_key( 
key_id ) );
             }
             return it->second;
         }

         template< class Key_id >
         auto operator[]( const Key_id& key_id ) -> Item& { return 
forced_item( key_id ); }

         template< class Key_id >
         auto operator[]( const Key_id& key_id ) const
             -> const Item&
         {
             const auto it = Self::find( key_id );
             if( it == Self::end() ) {
                 throw out_of_range( "const-Map_::operator[] - no such 
key." );
             }
             return it->second;
         }
     };
}  // namespace my

auto main() -> int
{
     std::string_view key = "foo"sv;

     my::Map_<std::string, int>              a;
     auto it_a = a.find(key);    // OK

     std::map<std::string, int, std::less<>> b;
     auto it_b = b.find(key);    // OK

     //b[key] = 3; //! Gah
     //  binary '[': no operator found which takes a right-hand operand 
of type 'std::string_view'

     a[key] = 3;          // OK
     b[std::string(key)] = 3;    // OK but may construct a std::string 
without reason.
}


- Alf

Back to comp.lang.c++ | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

map[string_view] not compiling Paavo Helde <eesnimi@osa.pri.ee> - 2022-08-01 14:52 +0300
  Re: map[string_view] not compiling Bo Persson <bo@bo-persson.se> - 2022-08-01 14:32 +0200
    Re: map[string_view] not compiling Paavo Helde <eesnimi@osa.pri.ee> - 2022-08-01 17:11 +0300
      Re: map[string_view] not compiling Öö Tiib <ootiib@hot.ee> - 2022-08-01 13:30 -0700
        Re: map[string_view] not compiling Bo Persson <bo@bo-persson.se> - 2022-08-01 23:23 +0200
          Re: map[string_view] not compiling Öö Tiib <ootiib@hot.ee> - 2022-08-01 22:52 -0700
    Re: map[string_view] not compiling Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-08-04 08:31 -0700
  Re: map[string_view] not compiling "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-08-03 11:34 +0200
    Re: map[string_view] not compiling Juha Nieminen <nospam@thanks.invalid> - 2022-08-03 10:49 +0000
      Re: map[string_view] not compiling "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-08-03 13:38 +0200
        Re: map[string_view] not compiling Juha Nieminen <nospam@thanks.invalid> - 2022-08-04 06:16 +0000
    Re: map[string_view] not compiling Paavo Helde <eesnimi@osa.pri.ee> - 2022-08-03 14:43 +0300
      Re: map[string_view] not compiling "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-08-03 13:56 +0200

csiph-web