1

I want to do something like

std::vector<int> foobar()
{
    // Do some calculations and return a vector
}

std::vector<int> a = foobar();
ASSERT(a == {1, 2, 3});

is this possible?

dshepherd
  • 4,989
  • 4
  • 39
  • 46

4 Answers4

5

Unfortunately you cannot overload operator== to accept a std::initializer_list as the second argument (this is a language rule).

But you can define any other function to take a const reference to an initializer_list:

#include <iostream>
#include <algorithm>
#include <vector>

template<class Container1, typename Element = typename Container1::value_type>
bool equivalent(const Container1& c1, const std::initializer_list<Element>& c2)
{
    auto ipair = std::mismatch(begin(c1),
                               end(c1),
                               begin(c2),
                               end(c2));
    return ipair.first == end(c1);
}


int main() {
    std::vector<int> x { 0, 1, 2 };
    std::cout << "same? : " << equivalent(x, { 0 , 1 , 2 }) << std::endl;
}

expected result:

same? : 1
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • It's a shame you can't overload operators for initializer_list, do you know why that is? – dshepherd Nov 18 '15 at 13:40
  • I cannot think of a good reason for it. Perhaps simply because `std::initializer_list` is a 'special' class which has one design goal - to facilitate constructors of containers from literals? We'd need to ask someone who was involve with the standard for the reason (if indeed there is one). – Richard Hodges Nov 18 '15 at 13:48
  • I found [this question](http://stackoverflow.com/questions/11420448/initializer-lists-and-rhs-of-operators): it seems like parsing initialiser lists as the LHS of operators would be too difficult, so operator overloads were disallowed entirely. – dshepherd Nov 18 '15 at 13:51
3

Yes:

ASSERT(a == std::vector<int>{1,2,3});
Šimon Tóth
  • 35,456
  • 20
  • 106
  • 151
  • I was hoping there was a way to do it without the `std::vector`. – dshepherd Nov 18 '15 at 13:21
  • @dshepherd : Then how do you identify the container? There should be a difference in the output of the assert statement if `a` is a vector of 1,2,3 or an unordered_map containing 1,2,3. – therainmaker Nov 18 '15 at 13:24
  • If ASSERT is a macro, remember to add other parenthesis: `ASSERT((a == std::vector{1, 2, 3}));` or it will not compile. – vincentp Nov 18 '15 at 13:24
  • 1
    @vincentp If this is true, then the implementation of `ASSERT` is wrong. Correctly written macros should not require you to use special syntax to invoke them. – Šimon Tóth Nov 18 '15 at 13:26
  • @therainmaker I wouldn't expect it to allow comparisons with an unordered map, but it could compare to vectors, arrays and sets. – dshepherd Nov 18 '15 at 13:32
  • @dshepherd : I meant unordered_sets in my previous comment. Apologies for that. But my previous point holds. Are you saying you want to implement something like container invariant comparison? That doesn't seem right. – therainmaker Nov 18 '15 at 13:53
1

You have explicitly to specify the type of the right hand operand. For example

std::vector<int> v = { 1, 2, 3 };
assert( v == std::vector<int>( { 1, 2, 3 } ) );

because the operator == is a template function and the compiler is unable to deduce the second operand to the type std::vector<int>

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

The most natural and/or 'prettiest' working implementation that I am aware of, assuming that what you want to do is impossible (as people on this site have said multiple times), is to typedef your vector type as follows:

typedef std::vector<int> vec;

ASSERT(a == vec({1, 2, 3}));

... where vec is named whatever you want.

If someone knows of something even more natural, please let us know.

Pulseczar
  • 150
  • 8