对我最近的回答What other useful 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
}
我的断言是第一个函数调用是一个错误,因为没有从const char *到A的转换。有一个从字符串到A的转换,但是使用它会涉及多个转换。我的理解是这是不允许的,这似乎是由g ++ 4.4.0&amp; Comeau编译器。使用Comeau,我收到以下错误:
"ComeauTest.c", line 11: error: no suitable constructor exists
to convert from "const char [4]" to "A"
func( "one" ); // error
如果你能指出我错在哪里,无论是在这里还是在原始答案中,最好是参考C ++标准,请这样做。
C ++标准的答案似乎是:
最多一个用户定义的转化 (构造函数或转换函数) 隐式应用于单个值。
感谢Abhay提供报价。
答案 0 :(得分:12)
我认为尖锐的答案是准确的。标题为“转换”的C ++标准(SC22-N-4411.pdf)第12.3.4节明确规定只允许一个隐式的用户定义转换。
1类对象的类型转换可以通过指定 构造函数和转换 功能。这些 转换称为用户定义的转换并被使用 用于隐式类型转换(Clause 4),为 初始化(8.5),以及显式类型转换(5.4, 5.2.9)。
2用户定义的转换仅适用于它们的位置 明确的(10.2,12.3.2)。 转换遵守 访问控制规则(第11条)。之后应用访问控制 歧义解决方案(3.4)。
3 [注意:有关转换使用的讨论,请参见13.3 在函数调用和示例中 下面。 -结束 注意]
4最多一个用户定义的转换(构造函数或转换 function)隐式应用于a 单 值。
答案 1 :(得分:9)
由于似乎已达成共识:是的,你是对的。
但是由于这个问题/答案可能会成为C ++隐式转换在stackoverflow上的参考点,我想为模板参数添加规则是不同的。
对于用于模板参数推断的参数,不允许隐式转换。这可能看起来很明显,但仍然会导致微妙的怪异。
例如,std :: string加法运算符
std::string s;
s += 67; // (1)
s = s + 67; // (2)
(1)编译并正常工作,operator+=
是一个成员函数,模板字符参数已经通过实例化std::string
获得s(char
)来推断。因此允许隐式转换(int
- &gt; char
),结果s包含等效于67的char,例如在ASCII中,这将成为'C'
(2)给出编译器错误,因为operator+
被声明为自由函数,这里模板字符参数 用于演绎。
答案 2 :(得分:8)
这是真的,只允许一次隐式转换。
连续两次转换可以使用转换运算符和参数化构造函数的组合执行,但这会导致C4927 warning - “非法转换;已隐式应用了多个用户定义的转换” - VC ++是有原因的。
答案 3 :(得分:7)
The C++ Programming Language(第4版)(第18.4.3节)说
只有一个级别的用户定义 隐式转换是合法的
“用户定义”部分听起来好像有些隐式转换可能是允许的,如果有些是本机类型之间的。