我有以下代码片段:
class A
{
public:
A() : x_(0), y_(0) {}
A(int x, int y) : x_(x), y_(y) {}
template<class T>
A(const T &rhs) : x_(rhs.x_), y_(rhs.y_)
{
}
int x_, y_;
};
class B
{
public:
B() {}
operator A() const { return A(c[0],c[1]); }
int c[2];
};
void f()
{
B b;
(A)b; // << here the error appears, compiler tries to use
// template<class T> A(const T &rhs)
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器使用A的构造函数?如何使用B转换运算符A?
我用的是MSVS2010编译器.它给了我这些错误:
main.cpp(9): error C2039: 'x_' : is not a member of 'B'
main.cpp(17) : see declaration of 'B'
main.cpp(28) : see reference to function template instantiation 'A::A<B>(const T &)' being compiled
with
[
T=B
]
main.cpp(9): error C2039: 'y_' : is not a member of 'B'
main.cpp(17) : see declaration of 'B'
Run Code Online (Sandbox Code Playgroud)
UPD:好吧,Nawaz所说的真正有效的隐式转换.让它变得更复杂,如何使下面的代码工作?
void f()
{
std::vector<B> b_vector(4);
std::vector<A> a_vector( b_vector.begin(), b_vector.end() );
}
Run Code Online (Sandbox Code Playgroud)
UPD:A是第三方库中的类,我无法编辑代码,所以我无法删除A转换构造函数.
UPD:我目前发现的最简单的解决方案是定义转换构造函数的特化B.它可以在第三方lib之外完成:
template<> A::A( const B &rhs ) : x_(rhs.c[0]), y_(rhs.c[1]) {}
Run Code Online (Sandbox Code Playgroud)
原因是不只是因为它认为(A)b是一样的A(b).标准说明了关于显式类型转换(5.4):
由...执行的转换
一个const_cast(5.2.11),
一个static_cast(5.2.9),
static_cast后跟const_cast,
reinterpret_cast(5.2.10),或
一个reinterpret_cast后跟一个const_cast,
可以使用显式类型转换的强制转换表示法执行.适用相同的语义限制和行为.
从本质上讲,这意味着即使对于显式类型转换(A)b(即,如果您曾经使用((A)b);它来防止它是变量声明).它使用的规则static_cast.现在让我们来看看标准所说的内容static_cast(5.2.9):
对于某些发明的临时变量t(8.5),如果声明"T t(e);"格式正确,则可以使用static_cast(e)形式的static_cast将表达式e显式转换为类型T. 这种显式转换的效果与执行声明和初始化,然后使用临时变量作为转换结果相同.如果T是引用类型(8.3.2),则结果是左值,否则为右值.当且仅当初始化将其用作左值时,表达式e用作左值.
如果你这样做static_cast<A>(b),它基本上看是否A(b)是良好的形式; 并且它是.仅仅因为模板函数copy-constructor的实际实例化失败,它不会使实际声明形成错误,因此它使用它并最终失败.
从5.4/1和5.4/5开始,C-cast从列表中选择"最佳选择"C++.在这种情况下,那是一个static_cast.
然后从5.2.9/2:
对于某些发明的临时变量t(8.5),如果声明"T t(e);"形成良好,则可以使用static_cast(e)形式的static_cast将表达式e显式地转换为类型T. 这种显式转换的效果与执行声明和初始化,然后使用临时变量作为转换结果相同.如果T是引用类型(8.3.2),则结果是左值,否则为右值.当且仅当初始化将其用作左值时,表达式e用作左值.
所以它在尝试任何其他选项之前选择构造函数.
在这种情况下,您已定义了两个转换以获得相同的最终结果,但该语言具有特定的规则,规定它将始终使用可用的构造函数.您应该离开构造函数并将操作符更改为显式as类型函数.
编辑OP的编辑:我认为你不能使用矢量iter, iter构造函数.你需要从一个空向量开始,并使用for循环push_back或使用std::transform.
(A)b; // << here the error appears, compiler tries to use
Run Code Online (Sandbox Code Playgroud)
这是显式 转换为A. 因此, 的构造函数A被调用以转换b为A.
A a(1,2);
a = b ; //this will invoke user-defined conversion of B (implicit conversion)
Run Code Online (Sandbox Code Playgroud)
演示: http: //www.ideone.com/K9IxT