为什么构造函数不会为给定的转换操作符调用? [英] Why constructor is not called for given casting operator?

查看:190
本文介绍了为什么构造函数不会为给定的转换操作符调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  struct A {}; 
struct B
{
B(A * pA){}
B& operator =(A * pA){return * this; }
};

template< typename T>
struct Wrap
{
T * x;
operator T *(){return x; }
};

int main()
{
Wrap< A>一个;
B oB = a; //错误:从'Wrap< A>'转换为非标量类型'B'请求
oB = a; // ok
}

oB 构造,则为 Wrap< T> :: operator T()不调用 B :: B(A *) c $ c>? [注意: Wrap< T> :: operator T() B :: operator =(A *) >在下一条语句中]

解决方案

问题是隐式调用的用户定义转换数量有限

  B ob = a; 

意味着两个用户转化:




  • a Wrap< A> :: operator A *() / li>
  • 在结果中: B :: B(A *)

    @James Kanze的解释:此语法称为复制初始化,实际上等效于 B ob = B(a)(复制在大多数时间被删除)。这不同于 B ob(a),这是一个直接初始化并且可以工作。



    if你明确限定任何这些,它将工作,例如:

      B ob = B 

    另一方面,对于第二种情况,没有问题:

      ob = a; 

    是短语:

      ob.operator =(a); 

    因此只需要一个用户定义的转换。



    EDIT



    由于在评论中需要(基里尔的回答)



    链接的转化可能很长,很长,因此:




    • 可能会让用户感到惊讶 - 隐式转换可能已经令人惊讶,因为...

    • 可能导致对编译器的可能性的指数搜索 - 从两端开始,尝试检查所有可能的转化,并以某种方式加入两个(可能的最短路径)。



    此外,只要有多于一个转换,就会遇到循环的风险,这些循环必须被检测到(即使可能不需要诊断,并且要遵守执行质量)。



    因此,由于限制是必要的,以避免无限长的搜索(它可能是未指定,有最低要求),并且从超过1,我们可能有新的问题(周期) ,那么1似乎是一个极限的任何毕竟。


    struct A {}; 
    struct B
    {
      B (A* pA) {}
      B& operator = (A* pA) { return *this; }
    };
    
    template<typename T>
    struct Wrap
    {
      T *x; 
      operator T* () { return x; }
    };
    
    int main ()
    {
      Wrap<A> a;
      B oB = a; // error: conversion from ‘Wrap<A>’ to non-scalar type ‘B’ requested
      oB = a;  // ok
    }
    

    When oB is constructed then Why B::B(A*) is NOT invoked for Wrap<T>::operator T () ? [Note: B::operator = (A*) is invoked for Wrap<T>::operator T () in the next statement]

    解决方案

    The problem is that the number of user-defined conversions that are invoked implicitly is limited (to 1) by the Standard.

    B ob = a;
    

    implies two user conversions:

    • on a: Wrap<A>::operator A*() should be called
    • on the result: B::B(A*) should be called

    @James Kanze's explanation: this syntax is called "copy initialization", effectively equivalent to B ob = B(a) (with the copy being elided most of the time). This is different from B ob(a) which is a "direct initialization" and would have worked.

    if you explicitly qualify any of this, it will work, for example:

    B ob = B(a);
    

    On the other hand, for the second case there is no issue:

    ob = a;
    

    is short-hand for:

    ob.operator=(a);
    

    And thus only one user-defined conversion is required, which is allowed.

    EDIT:

    Since it's been required in a comment (to Kirill's answer) we can take a guess at the motive.

    Chained conversions could be long, very long, and therefore:

    • could surprise users -- implicit conversions may already be surprising as it is...
    • could lead to an exponential search of the possibilities (for the compiler) -- it would need to go from both ends, trying to check all possible conversions, and somehow "join" the two (with the shortest path possible).

    Furthermore, as long as there is more than 1 conversion, you run into the risk of having cycles, which would have to be detected (even though diagnostic would probably not be required, and be subject to Quality Of Implementation).

    So, since a limit is necessary to avoid infinitely long searches (it could have been left unspecified, with a minimum required), and since beyond 1 we may have new issues (cycles), then 1 seems as good a limit as any after all.

    这篇关于为什么构造函数不会为给定的转换操作符调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆