偏好转换运算符而非转换构造函数

pur*_*ess 11 c++

我有以下代码片段:

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)

rek*_*o_t 9

原因是只是因为它认为(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的实际实例化失败,它不会使实际声明形成错误,因此它使用它并最终失败.


Mar*_*k B 5

从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.


Naw*_*waz 3

(A)b; // << here the error appears, compiler tries to use 
Run Code Online (Sandbox Code Playgroud)

这是显式 转换为A. 因此, 的构造函数A被调用以转换bA.

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