【问题标题】:Why is std::initializer_list conversion not preferred?为什么 std::initializer_list 转换不是首选?
【发布时间】:2018-07-18 01:42:25
【问题描述】:

考虑一下这个sn-p:

#include <iostream>
#include <vector>

void f(std::vector<int>){std::cout << __PRETTY_FUNCTION__ << '\n';}
void f(int x){std::cout << __PRETTY_FUNCTION__ << '\n';}

int main() 
{
    f({42});
}

Live on Coliru

如果你运行它,你可以看到f(int) 重载是首选,即使std::vector 有一个std::initializer_list constructor(参见#8)。

问题:为什么首选将{42} 转换为int(而不是转换为std::vector,因为{42}std::initializer_list)?

【问题讨论】:

  • 这被标记为 [c++11] 但链接的 Coliru 是用 -std=c++17 编译的。虽然不影响问题,但不一致感觉不对。
  • {42} 不是std::initializer_list。它是大括号中的int。它不是表达式,也没有类型。
  • @NickyC 修改

标签: c++ c++11 initializer-list overload-resolution


【解决方案1】:

在重载决议中,当考虑implicit conversion sequence in list-initialization时,

(强调我的)

否则,如果参数类型不是类和初始化器 list只有一个元素,隐式转换序列就是那个 需要将元素转换为参数类型

给定f({42});,对于f(int),隐式转换序列是将元素(即42)转换为int,这是完全匹配的;对于f(std::vector&lt;int&gt;),需要用户定义的转换(将std::initializer_list&lt;int&gt; 转换为std::vector&lt;int&gt;),这是一个更糟糕的匹配。

PS:如果大括号初始化器包含多个元素,例如{42, 42},则会选择f(std::vector&lt;int&gt;)

【讨论】:

    猜你喜欢
    • 2013-02-18
    • 1970-01-01
    • 1970-01-01
    • 2012-07-09
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    相关资源
    最近更新 更多