简体   繁体   English

C ++隐式转换

[英]C++ implicit conversions

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. 关于我最近回答的一些评论, 在C ++中可以使用的其他有用的演员表明,我对C ++转换的理解是错误的。 Just to clarify the issue, consider the following code: 只是为了澄清问题,请考虑以下代码:

#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. 我的断言是第一个函数调用是一个错误,因为没有从const char *到A的转换。有一个从字符串到A的转换,但是使用它会涉及多个转换。 My understanding is that this is not allowed, and this seems to be confirmed by g++ 4.4.0 & Comeau compilers. 我的理解是这是不允许的,这似乎是由g ++ 4.4.0和Comeau编译器证实的。 With Comeau, I get the following error: 使用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提供报价。

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. 标题为“转换”的C ++标准(SC22-N-4411.pdf)第12.3.4节明确指出,只允许一个隐式的用户定义转换。

1 Type conversions of class objects can be specified by constructors and by conversion functions. 1类对象的类型转换可以由构造函数和转换函数指定。 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). 这些转换称为用户定义的转换,用于隐式类型转换(第4节),初始化(8.5)和显式类型转换(5.4,5.2.9)。

2 User-defined conversions are applied only where they are unambiguous (10.2, 12.3.2). 2用户定义的转换仅在明确无误的情况下应用(10.2,12.3.2)。 Conversions obey the access control rules (Clause 11). 转换遵守访问控制规则(第11条)。 Access control is applied after ambiguity resolution (3.4). 模糊度解决(3.4)后应用访问控制。

3 [ Note: See 13.3 for a discussion of the use of conversions in function calls as well as examples below. 3 [注意:有关在函数调用中使用转换的讨论以及下面的示例,请参见13.3。 —end note ] - 尾注]

4 At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value. 4最多只有一个用户定义的转换(构造函数或转换函数)隐式应用于单个值。

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

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::string for s (to char ). (1)编译和工作正常, operator+=是一个成员函数,模板字符参数已经通过实例化std::string for s(to char )推断出来。 So implicit conversions are allowed ( int -> char ), results in s containing the char equivalent of 67, eg in ASCII this would become 'C' 因此允许隐式转换( int - > char ),结果s包含等效于67的char,例如在ASCII中这将成为'C'

(2) gives a compiler error as operator+ is declared as a free function and here the template character argument is used in deduction. (2)给出的编译器错误operator+被声明为免费功能,这里的模板字符参数扣除使用。

That's true, only one implicit conversion 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 ++中出于某种原因。

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. 如果某些部分位于本机类型之间,那么“用户定义”部分听起来就像允许多次隐式转换一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM