Why can't std::pair be compared to std::initiliazer_list

335 Views Asked by At

For std::pair, I am just curious to know why this works

std::pair<int, int> response = {1, 2}

while, this doesn't:

if (response == {1, 2}) do something;

Is it because the operator = is overloaded for std::pair while == isn't?

2

There are 2 best solutions below

4
On BEST ANSWER

This is just syntax: braced-init-list can be an operand only to [] and () (on the inside) and = and any @= (on the right). The initialization case is also allowed, where there is no operator at all.

2
On

People have already provided the answer. I would just want to add.

EDIT: The second one is not a comparison with an std::initializer_list and is invalid syntax actually since something like {1,2} doesn't have any inherent type as such (try decltype({1,2}) x. That's the language's syntax for list-initialization which fails since this isn't a statement for initialization per se unlike x{1,2}/x = {1,2}/foo({1,2}) etc. Something like {1,2} can be used to construct an initializer_list using list-initialization but isn't an std::initializer_list in itself.

Comaprison operators between an std::pair and an std::initializer_list are not available and probably for a good reason because an initializr_list is a

lightweight proxy object that provides access to an array of objects of type const T.

Note that the type of all the members of an initializer_list is of the same type const T. This isn't the case for a pair that usually has distinct types T and U.

If you want, you could write an equality function between a pair and an initializer_list something as follows, obviously adhering to many constraints:

#include <iostream>
#include <type_traits>
#include <utility>
#include <initializer_list>

template <typename T, typename U>
bool foo(const std::pair<T, U>&pair,
 const std::initializer_list<std::common_type_t<T, U>>& list) {
     if(list.size() != 2) {
         return false;
     }
     auto it = begin(list);
     return pair.first == *it && pair.second == *std::next(it);
}

int main() {
    {
        std::pair<int, int> pair {1, 3};
        std::initializer_list<int> list {1, 2};
        std::cout<<std::boolalpha<<foo(pair, list)<<'\n';
    }
    {
        std::pair<int, int> pair {1, 2};
        std::initializer_list<int> list {1, 2};
        std::cout<<std::boolalpha<<foo(pair, list)<<'\n';
    }
    {
        std::pair<int, int> pair {1, 2};
        std::initializer_list<int> list {1, 2, 3};
        std::cout<<std::boolalpha<<foo(pair, list)<<'\n';
    }
    {
        std::pair<int, char> pair {1, 2}; //common type is int
        std::initializer_list<int> list {1, 2};
        std::cout<<std::boolalpha<<foo(pair, list)<<'\n';
    }
    {
        // std::pair<int, long> pair {1, 2}; //common type is long int
        // std::initializer_list<int> list {1, 2}; //fails template substitution
        // std::cout<<std::boolalpha<<foo(pair, list)<<'\n';
    }
    {
        std::pair<int, long> pair {1, 2}; //common type is long int
        std::initializer_list<long int> list {1, 2}; //same as common type of pair
        std::cout<<std::boolalpha<<foo(pair, list)<<'\n';
    }
    {
        std::pair<int, long> pair {1, 2}; //common type is long int
        if(foo(pair, {1, 2})) {
            std::cout<<"Matched\n";
        }
    }
}