【问题标题】:Why can't std::pair be compared to std::initiliazer_list为什么 std::pair 不能与 std::initiliazer_list 进行比较
【发布时间】:2021-04-15 20:48:14
【问题描述】:

对于std::pair,我只是想知道为什么会这样

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

虽然,这不是:

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

是不是因为 = 运算符重载了 std::pair 而 == 没有重载?

【问题讨论】:

  • 第一个不是初始化列表,而第二个是。初始化器列表不能与pair一起使用,因为初始化器列表是同构的,而pair是异构数据结构。想想pair&lt;int, std::string&gt;
  • 第一个甚至不是operator=,是list-initialization

标签: c++ c++14 std-pair stdinitializerlist


【解决方案1】:

这只是语法:braced-init-list 可以是 []()(在内部)和 = 和任何@=(在右侧)。初始化情况也是允许的,根本没有操作符。

【讨论】:

  • 谢谢!有这方面的参考吗?
  • @Enqueue:我猜你的意思不是标准中的语法——cppreference covers it 列出了列表初始化的用途。
  • 因此,列表初始化与initializer_list不同,事实上,后者的对象是在执行列表初始化时自动创建的,或者在赋值期间用作右操作数。这种理解正确吗?
  • @Enqueue:它们是不同的,some list-initialization 会产生 std::initializer_list&lt;T&gt; 对象,但是 braced-init-list 的内容也可以直接使用(包括作为构造函数参数)。
【解决方案2】:

人们已经给出了答案。我只想补充。

编辑:第二个是 notstd::initializer_list 的比较,实际上是无效的语法,因为像 {1,2} 这样的东西没有任何固有的 type 作为这样的(尝试decltype({1,2}) x。这是list-initialization 的语言语法失败,因为这不是初始化 本身不像x{1,2}/x = {1,2}/foo({1,2}) 等的语句。像{1,2} 一样可以使用list-initialization构造一个initializer_list,但它本身不是一个std::initializer_list

std::pairstd::initializer_list 之间的比较运算符不可用,这可能是有充分理由的,因为 initializr_list is a

提供对对象数组的访问的轻量级代理对象 const T 类型。

请注意,initializer_list 的所有成员的类型都与const T 的类型相同。 pair 的情况并非如此,通常 具有不同的类型 TU

如果您愿意,您可以在 pairinitializer_list 之间编写一个相等函数,如下所示,显然要遵守许多约束:

#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";
        }
    }
}

【讨论】:

  • 这不是与 initializer_list 的比较:它甚至不解析,如果它解析了,它仍然不会是那个或任何其他类型的 表达式 .
  • @DavisHerring 你是对的。我已经更改了答案以反映这一点。
猜你喜欢
  • 2015-01-07
  • 2013-11-08
  • 2011-04-07
  • 1970-01-01
  • 2022-01-20
  • 2021-07-23
  • 2010-09-11
  • 1970-01-01
  • 2015-03-09
相关资源
最近更新 更多