了解涉及用户定义转换的过载解决方案排名 [英] Understanding overload resolution ranking involving user defined conversion

查看:91
本文介绍了了解涉及用户定义转换的过载解决方案排名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试了解过载分辨率.

首先让我们考虑第一种情况:

First let's consider this first case:

struct int1{
   int val;
   operator int&()&{
      return val;
      }
   operator const int &() const&{
      return val;
      }
    };

void f(int &){}       //f#1
void f(const int&){}  //f#2

void test1(){
  int1 x;
  f(x);
   //Conversion sequence for f#1: 
   //   - int_wrapper& --> int1::operator int&
   //   => Ranking: user defined conversion rank
   //Converison sequence for f#2:
   //   - int1& --> int1::operator int & --> const int&
   //   - int1& --> const int1 &         --> int1::operator const int& 
   //   => Ranking: ambiguous because 2 conversion sequence [over.best.ics]/10 
   //            => user defined conversion rank 
   //
   //=> No best viable overload, 2 user defined conversion rank 
}

不同于我的错误分析,编译器同意:f的调用不明确.为什么?

Unlike my wrong analysis, compilers agrees: the call to f is not ambiguous. Why?

现在考虑第二种情况,这非常相似,我只是将int&替换为int &&:

Now consider this second case, which is very similar, I just replace the int& by int &&:

struct int2{
   int val;
   operator int&&()&&{
      return std::move(val);
      }
   operator const int &() const&{
      return val;
      }
    };

void g(int &&){}     // g#1 
void g(const int&){} // g#2

void test2(){
  int2 x;
  g(std::move(x));
  //Conversions sequence for g#1 
  //   - int2&& --> int2::operator int&&
  //   => Ranking: user defined conversion rank
  //Conversion sequence for g#2 
  //   - int2&& --> const int2&           --> int2::operator const int&
  //   - int2&& --> int2::operator int&&  --> const int&
  //   => Ranking: ambiguous because 2 conversion sequence [over.best.ics]/10 
  //            => user defined conversion rank 
  //
  //=> No best viable overload, 2 user defined conversion rank 
  }

我的分析(在这种情况下也肯定是错误的)得出类似的结论,即对g的调用是模棱两可的.不幸的是,在第二种情况下,编译器不同意:

My analysis (which is certainly wrong in this case too) concludes similarly that the call to g is ambiguous. Unfortunatly, in this second case, compilers do not agree:

  • C语(3.4.1至5.0),MSVC 19 2017 RTW,Zapcc 190308(C语衍生),ellcc(0.1.33,0.1.34)(C语衍生)=>对g的调用含糊不清;
  • GCC(4.8.1至7.2),icc(16至18)=>对g的调用不明确.
  • Clang (3.4.1 to 5.0), MSVC 19 2017 RTW, Zapcc 190308 (Clang derivate), ellcc (0.1.33, 0.1.34)(Clang derivate) => call to g is ambiguous;
  • GCC (4.8.1 to 7.2), icc (16 to 18) => call to g is not ambiguous.

什么是正确的分析,哪个编译器是正确的?

What is the right analysis and which compiler is right?

您能否精确说明以下规则为何不适用或何时适用?

Could you precise why the rule below does not apply, or when is it applied?

[over.best.ics]/10:

如果存在几个不同的转换序列,每个转换序列都将参数转换为参数类型,则 与参数关联的隐式转换序列被定义为唯一转换序列 指定了 转换顺序不明确 .为了将隐式转换序列排名为 如16.3.3.2中所述,歧义转换序列被视为用户定义的转换序列 与任何其他用户定义的转换顺序都没有区别

If several different sequences of conversions exist that each convert the argument to the parameter type, the implicit conversion sequence associated with the parameter is defined to be the unique conversion sequence designated the ambiguous conversion sequence . For the purpose of ranking implicit conversion sequences as described in 16.3.3.2, the ambiguous conversion sequence is treated as a user-defined conversion sequence that is indistinguishable from any other user-defined conversion sequence

推荐答案

以下两个示例都是更简单的基本概念的更复杂表示:

Both of these examples are more complicated representations of simpler underlying concepts:

void f(int& );        // #1
void f(int const& );  // #2
void g(int&& );       // #3
void g(int const& );  // #4

int i;
f(i); // calls #1
g(0); // calls #3

对于第一个呼叫,我们倾向于使用更少的 cv 限定类型,因此int&int const&更好.对于第二个调用,我们赞成绑定到右值引用过度绑定到左值引用,因此int&&优于int const&.

For the first call, we favor the the less cv-qualified type, so int& is better than int const&. For the second call, we favor binding to rvalue reference over binding to lvalue reference, so int&& is better than int const&.

在特定示例中,这些首选项在通过隐式对象参数使用的转换函数的选择上表现出来.对于第一个示例,因为我们将隐式对象参数绑定到int1&以便转换为int&,但是将int1 const&绑定到int const&.同样,在第二个示例中,我们将隐式对象参数绑定到int2&&以便转换为int&&,但是将int2 const&绑定到int const&.

In the specific example, these preferences manifest themselves over the choice of conversion function used by way of the implicit object parameter. For the first example, because we're binding the implicit object parameter to int1& for converting to int&, but int1 const& for converting to int const&. Likewise, in the second example, we're binding the implicit object parameter to int2&& for converting to int&&, but int2 const& for converting to int const&.

我称其为c虫.

这篇关于了解涉及用户定义转换的过载解决方案排名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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