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

operator == on vectors

106 views
Skip to first unread message

Paul

unread,
Jun 12, 2016, 7:02:18 AM6/12/16
to
I don't seem to understand operators on vectors. I thought that you could write someVec == {} as a statement saying that someVec is empty.

However, this doesn't compile and I don't know why.
My error message is "expected primary-expression before '{' token".
I'd be grateful if someone could enlighten me. The complete code is below.
Thanks again for your help.

Paul

#include <vector>

int main()
{
std::vector<int> z;
if(z == {})
; // empty statement.
}

Victor Bazarov

unread,
Jun 12, 2016, 8:34:36 AM6/12/16
to
There is no operator== declared for std::vector. Equality operators are
not compiler-defined for user-defined classes. The library classes like
containers, streams, algorithms, etc. are user-defined from the language
point of view. Some of them (like std::string) do define operators like
== (as members or stand-alone functions). Most do not. You can find
more information on the available functionality if you just RTFM.

V
--
I do not respond to top-posted replies, please don't ask

Bonita Montero

unread,
Jun 12, 2016, 9:06:56 AM6/12/16
to
Am 12.06.2016 um 14:34 schrieb Victor Bazarov:

> There is no operator== declared for std::vector. ...

http://www.cplusplus.com/reference/vector/vector/operators/

--
http://facebook.com/bonita.montero/

Alf P. Steinbach

unread,
Jun 12, 2016, 9:25:50 AM6/12/16
to
* On 12.06.2016 14:34, Victor Bazarov wrote:
> * On 6/12/2016 7:02 AM, Paul wrote:
>> I don't seem to understand operators on vectors. I thought that you
>> could write someVec == {} as a statement saying that someVec is empty.
>>
>> However, this doesn't compile and I don't know why.
>> My error message is "expected primary-expression before '{' token".
>> I'd be grateful if someone could enlighten me. The complete code is
>> below.
>> Thanks again for your help.
>>
>> Paul
>>
>> #include <vector>
>>
>> int main()
>> {
>> std::vector<int> z;
>> if(z == {})
>> ; // empty statement.
>> }
>
> There is no operator== declared for std::vector. Equality operators are
> not compiler-defined for user-defined classes. The library classes like
> containers, streams, algorithms, etc. are user-defined from the language
> point of view. Some of them (like std::string) do define operators like
> == (as members or stand-alone functions). Most do not.

Adding to that...

With all standard containers (unless I'm mistaken, in which case, with
most all standard containers) you can use the misleadingly named member
function `empty` to check whether it's empty. Contrary to what the name
indicates, it does not empty the collection. It just checks.

std::bitset is not technically a container and has a differently named
empty checker, a method called `none`.

To get more readable code you can define an `is_empty` function for
vectors, like this:

template< class Item >
auto is_empty( std::vector<Item> const& v )
-> bool
{ return v.empty(); }

and then you can write more clearly

if( is_empty( z ) ) { ...

Defining such a wrapper for each container type of interest is some work
though. But defining a single general more smart wrapper that determines
if there is a boolean `empty` method and if so, uses it, is even more
work. I'm not posting my code for that, it would simply be too long, but
if you're interested you can look at it ¹at GitHub.

Cheers & hth.,

- Alf

Links:
¹
https://github.com/alf-p-steinbach/cppx/blob/master/source_code/cppx/core_language_support/sizes_and_lengths.hpp

Alf P. Steinbach

unread,
Jun 12, 2016, 9:35:24 AM6/12/16
to
On 12.06.2016 15:06, Bonita Montero wrote:
> Am 12.06.2016 um 14:34 schrieb Victor Bazarov:
>
>> There is no operator== declared for std::vector. ...
>
> http://www.cplusplus.com/reference/vector/vector/operators/
>

Victor jumped to the wrong conclusion, but it was so reasonable that I
posted a follow-up to that just assuming that he was right.

The actual issue is, I believe, purely syntactical: that the `{}` is
only supported syntactically in a (syntactically) function call.

For you /can/ write this:

if( std::operator==( z, {} ) )
; // empty statement.

Paavo Helde

unread,
Jun 12, 2016, 9:55:03 AM6/12/16
to
std::operator== is not a member of std::vector, it is a standalone
function which has many overloads. When you pass it z and {} it does not
know which overload because types are not the same and there is no exact
match.

There are a couple of workarounds:

a) cast/convert the operand into correct type manually:

if (z == std::vector<int>({}))


b) use a function which is not overloaded:

bool AreEqual(const std::vector<int>& a, const std::vector<int>& b) {
return a==b;
}

...
if (AreEqual(z, {}))

Of course, for the problem at hand you could rather use

if (z.empty())

instead, as suggested by Alf.

hth
Paavo

Paavo Helde

unread,
Jun 12, 2016, 10:15:22 AM6/12/16
to
On 12.06.2016 16:34, Alf P. Steinbach wrote:
> On 12.06.2016 15:06, Bonita Montero wrote:
>> Am 12.06.2016 um 14:34 schrieb Victor Bazarov:
>>
>>> There is no operator== declared for std::vector. ...
>>
>> http://www.cplusplus.com/reference/vector/vector/operators/
>>
>
> Victor jumped to the wrong conclusion, but it was so reasonable that I
> posted a follow-up to that just assuming that he was right.
>
> The actual issue is, I believe, purely syntactical: that the `{}` is
> only supported syntactically in a (syntactically) function call.

It is supported also in initialization

std::vector<int> z = {};
std::vector<int> z2 {};

>
> For you /can/ write this:
>
> if( std::operator==( z, {} ) )
> ; // empty statement.
>

Sorry, this does not work:

1>main.cpp(26): error C2665: 'std::operator ==' : none of the 5
overloads could convert all the argument types
1> C:\Program Files (x86)\Microsoft Visual Studio
12.0\VC\include\system_error(410): could be 'bool std::operator ==(const
std::error_condition &,const std::error_code &) throw()'
1> C:\Program Files (x86)\Microsoft Visual Studio
12.0\VC\include\system_error(402): or 'bool std::operator ==(const
std::error_code &,const std::error_condition &) throw()'
1> C:\Program Files (x86)\Microsoft Visual Studio
12.0\VC\include\exception(507): or 'bool std::operator ==(const
std::exception_ptr &,std::nullptr_t)'
1> C:\Program Files (x86)\Microsoft Visual Studio
12.0\VC\include\exception(502): or 'bool std::operator
==(std::nullptr_t,const std::exception_ptr &)'
1> C:\Program Files (x86)\Microsoft Visual Studio
12.0\VC\include\exception(497): or 'bool std::operator ==(const
std::exception_ptr &,const std::exception_ptr &)'
1> while trying to match the argument list
'(std::vector<int,std::allocator<_Ty>>, initializer-list)'
1> with
1> [
1> _Ty=int
1> ]




Alf P. Steinbach

unread,
Jun 12, 2016, 10:23:41 AM6/12/16
to
On 12.06.2016 16:15, Paavo Helde wrote:
> On 12.06.2016 16:34, Alf P. Steinbach wrote:
>> On 12.06.2016 15:06, Bonita Montero wrote:
>>> Am 12.06.2016 um 14:34 schrieb Victor Bazarov:
>>>
>>>> There is no operator== declared for std::vector. ...
>>>
>>> http://www.cplusplus.com/reference/vector/vector/operators/
>>>
>>
>> Victor jumped to the wrong conclusion, but it was so reasonable that I
>> posted a follow-up to that just assuming that he was right.
>>
>> The actual issue is, I believe, purely syntactical: that the `{}` is
>> only supported syntactically in a (syntactically) function call.
>
> It is supported also in initialization
>
> std::vector<int> z = {};
> std::vector<int> z2 {};

Yep, thanks!


>> For you /can/ write this:
>>
>> if( std::operator==( z, {} ) )
>> ; // empty statement.
>>
>
> Sorry, this does not work:
>
> 1>main.cpp(26): error C2665: 'std::operator ==' : none of the 5
> overloads could convert all the argument types
> 1> C:\Program Files (x86)\Microsoft Visual Studio
> 12.0\VC\include\system_error(410):

It's a Good Idea to compile code for C++11 and later, with a compiler
that supports the relevant feature(s).

You should upgrade from VS 2012 to VS 2015.

The latest update is 3, but I've only gotten around to 2.


{example}
[C:\my\forums\so\156]
> g++ --version | find "++"
g++ (tdm64-1) 5.1.0

[C:\my\forums\so\156]
> cl /nologo- 2>&1 | find "++"
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23725 for x86

[C:\my\forums\so\156]
> type foo.cpp
#include <vector>

int main()
{
std::vector<int> z;
if( std::operator==( z, {} ) )
; // empty statement.
}

[C:\my\forums\so\156]
> g++ foo.cpp
foo.cpp: In function 'int main()':
foo.cpp:7:7: warning: suggest braces around empty body in an 'if'
statement [-Wempty-body]
; // empty statement.
^

[C:\my\forums\so\156]
> cl foo.cpp /Feb
foo.cpp
foo.cpp(7): warning C4390: ';': empty controlled statement found; is
this the intent?

[C:\my\forums\so\156]
> _
{/example}

Which exemplifies that I'm not always so pedantically correct in where I
place the small example code snippets.

Hrmf.

Alf P. Steinbach

unread,
Jun 12, 2016, 10:29:05 AM6/12/16
to
On 12.06.2016 15:54, Paavo Helde wrote:
> On 12.06.2016 14:02, Paul wrote:
>>
>> … this doesn't compile and I don't know why.
>>
>> #include <vector>
>>
>> int main()
>> {
>> std::vector<int> z;
>> if(z == {})
>> ; // empty statement.
>> }
>>
>
> std::operator== is not a member of std::vector, it is a standalone
> function which has many overloads. When you pass it z and {} it does not
> know which overload because types are not the same and there is no exact
> match.

No no, passing `z` and `{}` /to the function/ is supported and works
nicely with modern compilers.

It's the operator notation that doesn't support `{}`.

Else-thread you remarked that it's not only supported syntactically for
function calls, but also for initializers. And I can add to that, also
for `return` statements. Which however can be regarded as initialization
of the returned object.

[snip]

Paavo Helde

unread,
Jun 12, 2016, 10:29:43 AM6/12/16
to
On 12.06.2016 17:15, Paavo Helde wrote:
> On 12.06.2016 16:34, Alf P. Steinbach wrote:
>>
>> For you /can/ write this:
>>
>> if( std::operator==( z, {} ) )
>> ; // empty statement.
>>
>
> Sorry, this does not work:

Correction: it seems this might accidentally work if one avoids
including most standard headers (the errors in my previous post appeared
because of #include <iostream>). However, this is not guaranteed because
standard headers like <vector> can freely include other standard headers.

Alf P. Steinbach

unread,
Jun 12, 2016, 10:32:20 AM6/12/16
to
I can report that it works niceley with `<iostream>` included, with g++
5.1 and MSVC 2015.

And there's no accident about it. :)

Paavo Helde

unread,
Jun 12, 2016, 11:54:05 AM6/12/16
to
I see. That's nice to hear. It seems I need to upgrade indeed.

I wonder if there have been any changes in this area in C++ standards or
is it just another MSVC bug?

Cheers
Paavo


Vir Campestris

unread,
Jun 12, 2016, 1:15:15 PM6/12/16
to
On 12/06/2016 15:22, Alf P. Steinbach wrote:
> You should upgrade from VS 2012 to VS 2015.
>
> The latest update is 3, but I've only gotten around to 2.

I take it you heard about the telemetry thing?

Andy

K. Frank

unread,
Jun 13, 2016, 8:10:24 AM6/13/16
to
Hi Alf (and Friends)!

Thank you for this discussion on one of the musty (for
me) corners of c++ syntax.

But why?

On Sunday, June 12, 2016 at 9:35:24 AM UTC-4, Alf P. Steinbach wrote:
> On 12.06.2016 15:06, Bonita Montero wrote:
> > Am 12.06.2016 um 14:34 schrieb Victor Bazarov:
> >
> >> There is no operator== declared for std::vector. ...
> > ...
>
> Victor jumped to the wrong conclusion, ...
>
> The actual issue is, I believe, purely syntactical: that the `{}` is
> only supported syntactically in a (syntactically) function call.
>
> For you /can/ write this:
>
> if( std::operator==( z, {} ) )
> ; // empty statement.
>

My test version:

#include <vector>
int main (int argc, char* argv[]) {
std::vector<int> v;

// bool b = (v == {}); // doesn't compile
bool b = operator==(v, {}); // compiles

return 0;
}

I did this test with g++ -std=c++11, with version 4.9.2.

Note, I got rid of the std:: in front of operator== just
to make sure that this wasn't dome adl thing (not that it
should have been).

I think I understand what everyone is saying, and what the
issue is, but why? Which pieces of the standard work together?
Why is "v == {}" not effectively equivalent to
"operator==(v, {})"?

(And, although I expect not, is there any difference here
between c++11 and c++14 / c++17?)

> Cheers & hth.,
>
> - Alf


Thanks for any standardese parsing.


K. Frank

Juha Nieminen

unread,
Jun 14, 2016, 2:16:41 AM6/14/16
to
Paul <peps...@gmail.com> wrote:
> if(z == {})

I hope you are doing that only out of curiosity, experimenting and learning,
not in actual code. Obviously in actual code you would use z.empty().

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Jorgen Grahn

unread,
Jun 14, 2016, 2:36:54 AM6/14/16
to
On Sun, 2016-06-12, Alf P. Steinbach wrote:
...
> With all standard containers (unless I'm mistaken, in which case, with
> most all standard containers) you can use the misleadingly named member
> function `empty` to check whether it's empty. Contrary to what the name
> indicates, it does not empty the collection. It just checks.

It's a matter of point of view. I don't find it misleading but rather
natural ... or at least in line with the standard library naming
conventions in general.

...
> To get more readable code you can define an `is_empty` function for
> vectors, like this:
>
> template< class Item >
> auto is_empty( std::vector<Item> const& v )
> -> bool
> { return v.empty(); }

We've had empty() for around 25 years; I don't think it's helpful to
introduce an alias. Not if more than one person sees the code, anyway.

This on the other hand is one thing I sometimes wish for, since I
tend to want to negate the empty() check:

if (!foobar.empty()) ... // hard to spot the negation

if (not foobar.empty()) ... // few use the 'not' alias

if (foobar.non_empty()) ... // better

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Öö Tiib

unread,
Jun 14, 2016, 7:44:41 AM6/14/16
to
On Tuesday, 14 June 2016 09:36:54 UTC+3, Jorgen Grahn wrote:
> On Sun, 2016-06-12, Alf P. Steinbach wrote:
> ...
> > With all standard containers (unless I'm mistaken, in which case, with
> > most all standard containers) you can use the misleadingly named member
> > function `empty` to check whether it's empty. Contrary to what the name
> > indicates, it does not empty the collection. It just checks.
>
> It's a matter of point of view. I don't find it misleading but rather
> natural ... or at least in line with the standard library naming
> conventions in general.

Hmm. Are you sure about naming "conventions" of standard library?
What is correct by those "conventions"? Is it 'vector::get_allocator()' or
'vector::allocator()'? Is it 'vector::capacity()' or 'vector::get_capacity()'?
Feels there are no such "conventions".

We typically expect functions to be requests of activities in imperative
programming language therefore usage of word that is both verb and
adjective ('empty') for function name in meaning of that adjective is
misleading. Frank way of naming such function would be 'is_empty'.

>
> ...
> > To get more readable code you can define an `is_empty` function for
> > vectors, like this:
> >
> > template< class Item >
> > auto is_empty( std::vector<Item> const& v )
> > -> bool
> > { return v.empty(); }
>
> We've had empty() for around 25 years; I don't think it's helpful to
> introduce an alias. Not if more than one person sees the code, anyway.

That is entirely another question if it is worth to try to repair such
minor legacy cosmetic defects in standard library or not. I do not think
that it is.

>
> This on the other hand is one thing I sometimes wish for, since I
> tend to want to negate the empty() check:
>
> if (!foobar.empty()) ... // hard to spot the negation

That depends on how your code editor colors the operators.

>
> if (not foobar.empty()) ... // few use the 'not' alias

These aliases are made like inbuilt macros so one can declare rvalue
reference 'foo' like that:

auto and foo = get_foo();

>
> if (foobar.non_empty()) ... // better

But also likely not worth it. Lot of developers (possibly majority)
write one of those instead:

if (foobar.size()) ... // the reality
if (0 < foobar.size()) ... // the reality
if (foobar.size() != 0) ... // the reality

I suspect that it is so (at least partially) because 'empty' is such a
bad name. ;-)

Wouter van Ooijen

unread,
Jun 14, 2016, 11:49:40 AM6/14/16
to
> We typically expect functions to be requests of activities in imperative
> programming language therefore usage of word that is both verb and
> adjective ('empty') for function name in meaning of that adjective is
> misleading. Frank way of naming such function would be 'is_empty'.

I agree 100%. I teach my students that a predicate should always
contains a verb like is, has, contains, includes, etc.

The other function (the one that makes something empty) should probably
be called make_empty().

Wouter "Objects? No Thanks!" van Ooijen

Jorgen Grahn

unread,
Jun 15, 2016, 10:32:35 PM6/15/16
to
On Tue, 2016-06-14, 嘱 Tiib wrote:
> On Tuesday, 14 June 2016 09:36:54 UTC+3, Jorgen Grahn wrote:
>> On Sun, 2016-06-12, Alf P. Steinbach wrote:
>> ...
>> > With all standard containers (unless I'm mistaken, in which case, with
>> > most all standard containers) you can use the misleadingly named member
>> > function `empty` to check whether it's empty. Contrary to what the name
>> > indicates, it does not empty the collection. It just checks.
>>
>> It's a matter of point of view. I don't find it misleading but rather
>> natural ... or at least in line with the standard library naming
>> conventions in general.
>
> Hmm. Are you sure about naming "conventions" of standard library?
> What is correct by those "conventions"? Is it 'vector::get_allocator()' or
> 'vector::allocator()'? Is it 'vector::capacity()' or 'vector::get_capacity()'?
> Feels there are no such "conventions".

Let's say "in line with the /lack/ of naming conventions", then.

> We typically expect functions to be requests of activities in imperative
> programming language therefore usage of word that is both verb and
> adjective ('empty') for function name in meaning of that adjective is
> misleading. Frank way of naming such function would be 'is_empty'.

There doesn't seem to be a lot of is_adjective() in the standard
library, though. Except in <type_traits>.

...
>> if (foobar.non_empty()) ... // better
>
> But also likely not worth it. Lot of developers (possibly majority)
> write one of those instead:
>
> if (foobar.size()) ... // the reality
> if (0 < foobar.size()) ... // the reality
> if (foobar.size() != 0) ... // the reality
>
> I suspect that it is so (at least partially) because 'empty' is such a
> bad name. ;-)

I think that if people write such code, it's because they usually want
the negation -- my "hard to spot the !" argument.

I don't think I've seen size() used that way. Maybe I've been
lucky. I have sometimes been tempted to write such code myself, but
after an incident with std::list (where size() at least /might/ be
O(n)) I hesitate to ask for more information than I'm really going to
need.

Jorgen Grahn

unread,
Jun 15, 2016, 10:42:51 PM6/15/16
to
On Tue, 2016-06-14, Wouter van Ooijen wrote:

[ÖT]
But still, the C++ containers have a different convention:

bool empty() const;
void clear();

For better or worse, I've adopted that convention. If I write a
container-like class and need that feature, I'll use those names.
I probably would even if I objected to them more than I do.
0 new messages