如果复制列表初始化允许显式构造函数,可能会出错? [英] What could go wrong if copy-list-initialization allowed explicit constructors?

查看:409
本文介绍了如果复制列表初始化允许显式构造函数,可能会出错?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++标准中,第13.3.1.7节[over.match.list]说明如下:

In the C++ standard, §13.3.1.7 [over.match.list], the following is stated:


列表初始化,如果选择显式构造函数,初始化是错误的。

In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.


$ b b

这就是为什么我们不能这样做的原因,例如:

This is the reason why we can't do, for example, something like this:

struct foo {
    // explicit because it can be called with one argument
    explicit foo(std::string s, int x = 0);
private:
    // ...
};

void f(foo x);

f({ "answer", 42 });

(请注意,这里发生的是不是转换并且它不会是一个即使构造函数是隐含的这是使用其构造函数直接初始化 foo 对象除了 std :: string ,这里没有转换。)

(Note that what happens here is not a conversion, and it would not be one even if the constructor was "implicit". This is initialization of a foo object using its constructor directly. Other than the std::string, there is no conversion here.)

如果 {answer,42} 可以初始化一些东西否则,编译器不会背叛我,做错了的事情:

If { "answer", 42 } can initialize something else, the compiler won't betray me and do the wrong thing:

struct bar {
    // explicit because it can be called with one argument
    explicit bar(std::string s, int x = 0);
private:
    // ...
};

void f(foo x);
void f(bar x);

f({ "answer", 42 }); // error: ambiguous call

没有问题:调用不明确,代码不会编译,我必须显式地选择重载。

There's no problem: the call is ambiguous, the code won't compile, and I'll have to pick the overload explicitly.

f(bar { "answer", 42 }); // ok

由于禁止明确说明,我觉得我在这里缺少了一些东西。就我所见,列表初始化挑选显式构造函数对我来说似乎不是一个问题:通过使用列表初始化语法程序员已经表达了做某种转换的愿望。

Since the prohibition is explicitly stated, I have the feeling that I am missing something here. As far as I can see, list initialization picking explicit constructors doesn't seem like a problem to me: by using list initialization syntax the programmer is already expressing the desire to do some kind of "conversion".

什么可能出错?

推荐答案

概念上,复制列表初始化是将复合值转换为目标类型。提出措辞和解释理由的论文已经考虑了复制列表初始化中的术语复制,这是不幸的,因为它没有真正传达其背后的实际理由。但是它保持与现有措辞的兼容性。 {10,20} pair / tuple值不能复制初始化 String(int size,int reserve),因为字符串不是一对。

Conceptually copy-list-initialization is the conversion of a compound value to a destination type. The paper that proposed wording and explained rationale already considered the term "copy" in "copy list initialization" unfortunate, since it doesn't really convey the actual rationale behind it. But it is kept for compatibility with existing wording. A {10, 20} pair/tuple value should not be able to copy initialize a String(int size, int reserve), because a string is not a pair.

显式构造函数被考虑,但是被禁止使用。这在以下情况下是有意义的:

Explicit constructors are considered but forbidden to be used. This makes sense in cases as follows

struct String {
  explicit String(int size);
  String(char const *value);
};

String s = { 0 };

0 串。因此,这会导致错误,因为会考虑两个构造函数,但选择显式构造函数,而不是 / code>被视为一个空指针常量。

0 does not convey the value of a string. So this results in an error because both constructors are considered, but an explicit constructor is selected, instead of the 0 being treated as a null pointer constant.

不幸的是,这也发生在跨函数的重载解析中。

Unfortunately this also happens in overload resolution across functions

void print(String s);
void print(std::vector<int> numbers);

int main() { print({10}); }

这也是不明确的。在C ++ 11之前发布的一些人(包括我)认为这是不幸的,但没有提出一个文件,提出一个改变(据我所知)。

This is ill-formed too because of an ambiguity. Some people (including me) before C++11 was released thought that this is unfortunate, but didn't came up with a paper proposing a change regarding this (as far as I am aware).

这篇关于如果复制列表初始化允许显式构造函数,可能会出错?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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