哪些贪婪的初始化列表示例潜伏在标准库中? [英] Which greedy initializer-list examples are lurking in the Standard Library?

查看:185
本文介绍了哪些贪婪的初始化列表示例潜伏在标准库中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于C ++ 11,标准库容器和 std :: string 有构造函数采用初始化列表。这个构造函数优先于其他构造函数(甚至,如评论中的@ JohannesSchaub-litb所指出的,甚至忽略其他最佳匹配标准)。当将所有括号()形式的构造函数转换为其支撑版本 {}时,会导致一些已知的陷阱

Since C++11, the Standard Library containers and std::string have constructors taking an initializer-list. This constructor takes precedence over other constructors (even, as pointed out by @JohannesSchaub-litb in the comments, even ignoring other "best match" criteria). This leads to a few well-known pitfalls when converting all parenthesized () forms of constructors to their braced versions {}

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>

void print(std::vector<int> const& v)
{
    std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ","));
    std::cout << "\n";
}

void print(std::string const& s)
{
    std::cout << s << "\n";
}

int main()
{
    // well-known 
    print(std::vector<int>{ 11, 22 });  // 11, 22, not 11 copies of 22
    print(std::vector<int>{ 11 });      // 11,     not 11 copies of 0

    // more surprising
    print(std::string{ 65, 'C' });      // AC,     not 65 copies of 'C'
}

在这个网站上的第三个例子,这个东西出现在休息室< C ++>聊天(与@rightfold,@Abyx和@JerryCoffin讨论)。有点令人惊讶的是,转换 std :: string ())的构造函数,将其含义从 n 更改为 n 字符(通常来自ASCII表)另一个字符。

I couldn't find the third example on this site, and the thing came up in the Lounge<C++> chat (in discussion with @rightfold, @Abyx and @JerryCoffin), The somewhat surprising thing is that converting the std::string constructor taking a count and a character to use {} instead of (), changes its meaning from n copies of the character to the n-th character (typically from the ASCII table) followed by the other character.

这不是通常禁止狭义转换,因为65是一个常量表达式可以表示为一个字符,将保留其原始转换回int(§8.5.4/ 7,bullet 4)(感谢@JerryCoffin)。

This is not caught by the usual brace prohibition on narrowing conversions, because 65 is a constant expression that can be represented as a char and will retain its original value when converted back to int (§8.5.4/7, bullet 4) (thanks to @JerryCoffin).

问题:更多的例子潜藏在标准库中,其中将()风格构造函数转换为 {} initializer-list构造函数? $ d $ b

Question: are there more examples lurking in the Standard Library where converting a () style constructor to {} style, is greedily matched by an initializer-list constructor?

推荐答案

我假设你的例子 std :: vector< int& std :: string 你也意味着覆盖其他容器,例如 std :: list< int& / code>, std :: deque< int> 等,这些都有相同的问题,显然, std :: vector< int> 。同样, int 不是唯一的类型,因为它也适用于 char short long 及其无符号版本(可能还有其他一些整数类型)。

I assume, with your examples for std::vector<int> and std::string you meant to also cover the other containers, e.g., std::list<int>, std::deque<int>, etc. which have the same problem, obviously, as std::vector<int>. Likewise, the int isn't the only type as it also applies to char, short, long and their unsigned version (possibly a few other integral types, too).

我想还有 std :: valarray< T> ,但我不确定 T 允许是整数类型。实际上,我认为这些具有不同的语义:

I think there is also std::valarray<T> but I'm not sure if T is allowed to be integral type. Actually, I think these have different semantics:

std::valarray<double>(0.0, 3);
std::valarray<double>{0.0, 3};

还有一些其他的标准C ++类模板需要 std :: initializer_list< T> 作为参数,但我不认为任何这些都有一个重载的构造函数,当使用括号而不是大括号时。

There are a few other standard C++ class templates which take an std::initializer_list<T> as argument but I don't think any of these has an overloaded constructor which would be used when using parenthesis instead of braces.

这篇关于哪些贪婪的初始化列表示例潜伏在标准库中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆