Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

std::map operator [] problems

85 views
Skip to first unread message

Christopher Pisz

unread,
Jun 16, 2015, 6:34:16 PM6/16/15
to
I am getting a compiler error:

Error 1 error C2678: binary '[' : no operator found which takes a
left-hand operand of type 'const
std::map<int,std::vector<std::string,std::allocator<_Ty>>,std::less<_Kty>,std::allocator<std::pair<const
_Kty,std::vector<_Ty,std::allocator<_Ty>>>>>' (or there is no
acceptable conversion) c:\users\christopher.pisz\documents\visual
studio 2013\projects\test\test\main.cpp 12 1 Test

With the following test:

#include <map>
#include <vector>

void Foo(const std::map<int, std::vector<std::string> > & theMap)
{
// If the map does not contain a value for the key
// I'd expect it to make an empty vector and return that
// but instead, I get a compiler error
const std::vector<std::string> stuff = theMap[1];
}

int main()
{
std::map<int, std::vector<std::string> > myMap;
std::vector<std::string> myVector;
myVector.push_back("Hello");
myVector.push_back("Good Bye");
myMap[1] = myVector;

Foo(myMap);

return 0;
}


I thought operator[] inserted a default constructed value if one did not
exist for the given key. I'd expect "Stuff" to be an empty vector, but I
get a compiler error instead. Where did I go wrong here?


--
I have chosen to troll filter/ignore all subthreads containing the
words: "Rick C. Hodgins", "Flibble", and "Islam"
So, I won't be able to see or respond to any such messages
---

Melzzzzz

unread,
Jun 16, 2015, 6:48:11 PM6/16/15
to
On Tue, 16 Jun 2015 17:34:05 -0500
Christopher Pisz <nos...@notanaddress.com> wrote:

> I am getting a compiler error:
>
> Error 1 error C2678: binary '[' : no operator found
> which takes a left-hand operand of type 'const
> std::map<int,std::vector<std::string,std::allocator<_Ty>>,std::less<_Kty>,std::allocator<std::pair<const
> _Kty,std::vector<_Ty,std::allocator<_Ty>>>>>' (or there is no
> acceptable conversion)
> c:\users\christopher.pisz\documents\visual studio
> 2013\projects\test\test\main.cpp 12 1 Test
>
> With the following test:
>
> #include <map>
> #include <vector>
>
> void Foo(const std::map<int, std::vector<std::string> > & theMap)
> {
> // If the map does not contain a value for the key
> // I'd expect it to make an empty vector and return that
> // but instead, I get a compiler error
> const std::vector<std::string> stuff = theMap[1];
> }
>
Get rid of the "const".

Christopher Pisz

unread,
Jun 16, 2015, 6:49:53 PM6/16/15
to
#include <iostream>
#include <map>
#include <vector>

void Foo(const std::map<int, std::vector<std::string> > & theMap)
{
// If the map does not contain a value for the key
// I'd expect it to make an empty vector and return that
// but instead, I get a compiler error
std::vector<std::string> stuff = theMap[1];
}

int main()
{
std::map<int, std::vector<std::string> > myMap;
std::vector<std::string> myVector;
myVector.push_back("Hello");
myVector.push_back("Good Bye");
myMap[1] = myVector;

Foo(myMap);

return 0;
}

Same error.
Were you referring to a different const?

Melzzzzz

unread,
Jun 16, 2015, 6:50:55 PM6/16/15
to
On Tue, 16 Jun 2015 17:49:45 -0500
void Foo(/* this const*/ std::map<int, std::vector<std::string> > &
theMap)

Christopher Pisz

unread,
Jun 16, 2015, 7:01:27 PM6/16/15
to
On 6/16/2015 5:50 PM, Melzzzzz wrote:
> On Tue, 16 Jun 2015 17:49:45 -0500
> Christopher Pisz <nos...@notanaddress.com> wrote:
>
>> On 6/16/2015 5:48 PM, Melzzzzz wrote:
>>> On Tue, 16 Jun 2015 17:34:05 -0500
>>> Christopher Pisz <nos...@notanaddress.com> wrote:
>>>
>>>> I am getting a compiler error:
>>>>
>>>> Error 1 error C2678: binary '[' : no operator found
>>>> which takes a left-hand operand of type 'const
>>>> std::map<int,std::vector<std::string,std::allocator<_Ty>>,std::less<_Kty>,std::allocator<std::pair<const
>>>> _Kty,std::vector<_Ty,std::allocator<_Ty>>>>>' (or there is no
>>>> acceptable conversion)
>>>> c:\users\christopher.pisz\documents\visual studio
>>>> 2013\projects\test\test\main.cpp 12 1 Test
>>>>
>>>> With the following test:
>>>>
>>>> #include <map>
>>>> #include <vector>
>>>>
>>>> void Foo(const std::map<int, std::vector<std::string> > & theMap)
>>>> {
>>>> // If the map does not contain a value for the key
>>>> // I'd expect it to make an empty vector and return that
>>>> // but instead, I get a compiler error
>>>> const std::vector<std::string> stuff = theMap[1];
>>>> }
>>>>
>>> Get rid of the "const".
SNIP
>
> void Foo(/* this const*/ std::map<int, std::vector<std::string> > &
> theMap)
>


Oh I see...Is it because of the scenario where the key doesn't exist, it
would have to default construct a vector, which in turn would alter the map?

Melzzzzz

unread,
Jun 16, 2015, 7:02:41 PM6/16/15
to
On Tue, 16 Jun 2015 18:01:18 -0500
Exactly.

Barry Schwarz

unread,
Jun 16, 2015, 7:09:55 PM6/16/15
to
On Tue, 16 Jun 2015 17:34:05 -0500, Christopher Pisz
<nos...@notanaddress.com> wrote:

>I am getting a compiler error:
>
>Error 1 error C2678: binary '[' : no operator found which takes a
>left-hand operand of type 'const
>std::map<int,std::vector<std::string,std::allocator<_Ty>>,std::less<_Kty>,std::allocator<std::pair<const
>_Kty,std::vector<_Ty,std::allocator<_Ty>>>>>' (or there is no
>acceptable conversion) c:\users\christopher.pisz\documents\visual
>studio 2013\projects\test\test\main.cpp 12 1 Test
>
>With the following test:
>
>#include <map>
>#include <vector>
>
>void Foo(const std::map<int, std::vector<std::string> > & theMap)
>{
> // If the map does not contain a value for the key
> // I'd expect it to make an empty vector and return that

This part of your expectation is a run time situation, not a compile
time determination.

> // but instead, I get a compiler error
> const std::vector<std::string> stuff = theMap[1];

It compiles fine on my system if you remove the "const" from Foo's
parameter.

The same compiler diagnostic is issued even if you remove the "&". So
the fact that the parameter is a reference is not the problem. It
apparently has something to do with the "const". I guess the []
operator is not defined for const map.

It compiles fine with the const if you change theMap[1] to
theMap.at(1) in the assignment statement.

>}
>
>int main()
>{
> std::map<int, std::vector<std::string> > myMap;
> std::vector<std::string> myVector;
> myVector.push_back("Hello");
> myVector.push_back("Good Bye");
> myMap[1] = myVector;
>
> Foo(myMap);
>
> return 0;
>}
>
>
>I thought operator[] inserted a default constructed value if one did not
>exist for the given key. I'd expect "Stuff" to be an empty vector, but I
>get a compiler error instead. Where did I go wrong here?

You are mixing run time and compile time "performance".

--
Remove del for email

Christopher Pisz

unread,
Jun 16, 2015, 7:15:08 PM6/16/15
to
Excellent. Thanks for the help.
In that case, I think I want to use this alternative, so I can promise
the caller I won't alter their map. No sense in using find here, as far
as I can tell. I've never used the "at" member though.

void Foo(const std::map<int, std::vector<std::string> > & theMap)
{
std::vector<std::string> & stuff = std::vector<std::string>();
try
{
stuff = theMap.at(1);
}
catch(std::out_of_range &)
{
// Leave the vector empty
}

// Iterate over the elements and do things.

Paavo Helde

unread,
Jun 17, 2015, 2:09:26 AM6/17/15
to
Christopher Pisz <nos...@notanaddress.com> wrote in
news:mlq86g$kob$1...@dont-email.me:

> I am getting a compiler error:
>
> Error 1 error C2678: binary '[' : no operator found which
> takes a left-hand operand of type 'const
> std::map<int,std::vector<std::string,std::allocator<_Ty>>,std::less<_Kt
> y>,std::allocator<std::pair<const
> _Kty,std::vector<_Ty,std::allocator<_Ty>>>>>' (or there is no
> acceptable conversion) c:\users\christopher.pisz\documents\visual
> studio 2013\projects\test\test\main.cpp 12 1 Test
>
> With the following test:
>
> #include <map>
> #include <vector>
>
> void Foo(const std::map<int, std::vector<std::string> > & theMap)
> {
> // If the map does not contain a value for the key
> // I'd expect it to make an empty vector and return that
> // but instead, I get a compiler error
> const std::vector<std::string> stuff = theMap[1];

void Foo(const std::map<int, std::vector<std::string> > & theMap)
{
auto iter = theMap.find(1);
const std::vector<std::string> stuff =
(iter==theMap.end()? std::vector<std::string>(): iter->second);
}

hth
Paavo

Richard

unread,
Jun 18, 2015, 12:27:17 AM6/18/15
to
[Please do not mail me a copy of your followup]

Christopher Pisz <nos...@notanaddress.com> spake the secret code
<mlq86g$kob$1...@dont-email.me> thusly:

>I am getting a compiler error:
>
>Error 1 error C2678: binary '[' : no operator found which takes a
>left-hand operand of type 'const
>std::map<int,std::vector<std::string,std::allocator<_Ty>>,std::less<_Kty>,std::allocator<std::pair<const
>_Kty,std::vector<_Ty,std::allocator<_Ty>>>>>' (or there is no
>acceptable conversion) c:\users\christopher.pisz\documents\visual
>studio 2013\projects\test\test\main.cpp 12 1 Test

There is no std::map::operator[] that is a const method. This is
because operator[] *creates* an entry in the map for the given key if
it doesn't already exist. If you want to find the value associated
with a key on a constant map, then use std::map::find.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

1971 powerChina

unread,
Jul 8, 2015, 10:08:34 PM7/8/15
to
在 2015年6月17日星期三 UTC+8上午6:34:16,Christopher Pisz写道:
you should use it
sourceforge.net/projects/pwwhashmap/

Alf P. Steinbach

unread,
Jul 9, 2015, 1:24:44 AM7/9/15
to
On 17-Jun-15 1:14 AM, Christopher Pisz wrote:
> [...] I think I want to use this alternative, so I can promise
> the caller I won't alter their map. No sense in using find here, as far
> as I can tell. I've never used the "at" member though.
>
> void Foo(const std::map<int, std::vector<std::string> > & theMap)
> {
> std::vector<std::string> & stuff = std::vector<std::string>();
> try
> {
> stuff = theMap.at(1);
> }
> catch(std::out_of_range &)
> {
> // Leave the vector empty
> }
>
> // Iterate over the elements and do things.
> }

Since you have declared `stuff` as a simple reference to non-`const`,
the initialization won't compile. A reference to non-`const` can only be
initialized with an lvalue expression, such as a reference to a
variable. However, it's not necessary to have `stuff` as a reference.

Also, note that using exceptions for normal case code (essentially to
provide a default) has a high cost, relative to non-exception based
code. Exceptions as used for failure handling can be very efficient,
because there they enable you to not do repeated checking in the normal
case code. But exceptions used for normal case code do the opposite:
they add checking that would otherwise not be there.

I would instead do something like this:

void foo( vector<string> const& stuff )
{
// Do things.
}

void foo( map<int, vector<string>> const& the_map )
{
vector<string> const empty_vector;
foo( the_map.count(1) > 0? the_map.at(1) : empty_vector );
}

But before doing that I'd check if the caller could explicitly provide
the information that lack of a 1-key implies.

And if measurements showed that repeated lookup was too inefficient, I'd
use a `find` and keep the resulting iterator.


Cheers & hth.,

- Alf

--
Using Thunderbird as Usenet client, Eternal September as NNTP server.

Christopher Pisz

unread,
Jul 9, 2015, 1:51:29 PM7/9/15
to
On 7/8/2015 9:08 PM, 1971 powerChina wrote:
> 在 2015年6月17日星期三 UTC+8上午6:34:16,Christopher Pisz写道:

> you should use it
> sourceforge.net/projects/pwwhashmap/
>

"Code cannot be used for commercial purposes"
user ratings: 1
Proof of performance: 0
0 new messages