C++ 隐式转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/867462/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:40:01  来源:igfitidea点击:

C++ implicit conversions

c++

提问by

Several comments on a recent answer of mine, What other useful casts can be used in C++, suggest that my understanding of C++ conversions is faulty. Just to clarify the issue, consider the following code:

对我最近的回答What other有用的 casts can be used in C++ 的几条评论表明我对 C++ 转换的理解是错误的。为了澄清这个问题,请考虑以下代码:

#include <string>

struct A {
    A( const std::string & s ) {}
};

void func( const A & a ) {
}

int main() {
    func( "one" );                  // error
    func( A("two") );           // ok
    func( std::string("three") );   // ok
}

My assertion was that the the first function call is an error, becauuse there is no conversion from a const char * to an A. There is a conversion from a string to an A, but using this would involve more than one conversion. My understanding is that this is not allowed, and this seems to be confirmed by g++ 4.4.0 & Comeau compilers. With Comeau, I get the following error:

我的断言是第一个函数调用是错误的,因为没有从 const char * 到 A 的转换。有从字符串到 A 的转换,但使用它会涉及多个转换。我的理解是这是不允许的,这似乎得到了 g++ 4.4.0 & Comeau 编译器的证实。使用 Comeau,我收到以下错误:

"ComeauTest.c", line 11: error: no suitable constructor exists 
      to convert from "const char [4]" to "A"
      func( "one" );                    // error

If you can point out, where I am wrong, either here or in the original answer, preferably with reference to the C++ Standard, please do so.

如果您能指出我错在哪里,无论是在这里还是在原始答案中,最好参考 C++ 标准,请这样做。

And the answer from the C++ standard seems to be:

而来自 C++ 标准的答案似乎是:

At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.

最多一个用户定义的转换(构造函数或转换函数)隐式应用于单个值。

Thanks to Abhay for providing the quote.

感谢 Abhay 提供报价。

采纳答案by Abhay

I think the answer from sharptooth is precise. The C++ Standard (SC22-N-4411.pdf) section 12.3.4 titled 'Conversions' makes it clear that only one implicit user-defined conversion is allowed.

我认为sharptooth的答案是准确的。标题为“转换”的 C++ 标准 (SC22-N-4411.pdf) 第 12.3.4 节明确说明只允许一种隐式的用户定义转换。

1 Type conversions of class objects can be specified by constructors and by conversion functions. These conversions are called user-defined conversions and are used for implicit type conversions (Clause 4), for initialization (8.5), and for explicit type conversions (5.4, 5.2.9).

2 User-defined conversions are applied only where they are unambiguous (10.2, 12.3.2). Conversions obey the access control rules (Clause 11). Access control is applied after ambiguity resolution (3.4).

3 [ Note: See 13.3 for a discussion of the use of conversions in function calls as well as examples below. —end note ]

4 At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.

1 类对象的类型转换可以由构造函数和转换函数指定。这些转换称为用户定义的转换,用于隐式类型转换(第 4 条)、初始化(8.5)和显式类型转换(5.4、5.2.9)。

2 用户定义的转换仅适用于明确的地方(10.2、12.3.2)。转换遵循访问控制规则(第 11 条)。在歧义解决(3.4)之后应用访问控制。

3 [ 注意:有关在函数调用中使用转换的讨论以及下面的示例,请参见 13.3。——尾注]

4 最多一个用户定义的转换(构造函数或转换函数)隐式应用于单个值。

回答by Pieter

As the consensus seems to be already: yes you're right.

似乎已经达成共识:是的,你是对的。

But as this question / answers will probably become the point of reference for C++ implicit conversions on stackoverflow I'd like to add that for template arguments the rules are different.

但是由于这个问题/答案可能会成为 stackoverflow 上 C++ 隐式转换的参考点,我想补充一点,对于模板参数,规则是不同的。

No implicit conversions are allowed for arguments that are used for template argument deduction. This might seem pretty obvious but nevertheless can lead to subtle weirdness.

对于用于模板参数推导的参数,不允许进行隐式转换。这可能看起来很明显,但仍然会导致微妙的怪异。

Case in point, std::string addition operators

例如,std::string 加法运算符

 std::string s;
 s += 67;    // (1)
 s = s + 67; // (2)

(1) compiles and works fine, operator+=is a member function, the template character parameter is already deduced by instantiating std::stringfor s (to char). So implicit conversions are allowed (int-> char), results in s containing the char equivalent of 67, e.g. in ASCII this would become 'C'

(1) 编译运行正常,operator+=是一个成员函数,模板字符参数已经通过实例化std::stringfor s (to char)推导出来。因此允许隐式转换(int-> char),导致 s 包含相当于 67 的字符,例如在 ASCII 中这将变为 'C'

(2) gives a compiler error as operator+is declared as a free function and here the template character argument isused in deduction.

(2)给出的编译器错误operator+被声明为免费功能,这里的模板字符参数在扣除使用。

回答by sharptooth

That's true, only one implicitconversion is allowed.

没错,只允许一种隐式转换。

Two conversions in a row may be performed with a combination of a conversion operator and a parameterized constructor but this causes a C4927 warning- "illegal conversion; more than one user-defined conversion has been implicitly applied" - in VC++ for a reason.

可以使用转换运算符和参数化构造函数的组合执行连续两次转换,但这会导致C4927 警告- “非法转换;隐式应用了多个用户定义的转换” - 在 VC++ 中是有原因的。

回答by Max Lybbert

The C++ Programming Language(4th. ed.)(section 18.4.3) says that

C++ 编程语言(第 4 版)(第 18.4.3 节)说

only one level of user-defined implicit conversion is legal

只有一层用户定义的隐式转换是合法的

That "user-defined" part makes it sound like multiple implicit conversions may be allowed if some are between native types.

如果某些在本机类型之间,则“用户定义”部分听起来可能允许多个隐式转换。