【问题标题】:Why are different conversion functions for int and const int allowed?为什么允许 int 和 const int 的不同转换函数?
【发布时间】:2018-11-29 08:56:47
【问题描述】:

为什么允许在 C++ 中编译以下内容?

#include<iostream>
using namespace std;

class mytest
{
public:    
    operator int()
    {
        return 10;
    }

    operator  const int()
    {
        return 5;
    }
};

int main()
{
    mytest mt;
    //int x = mt;    //ERROR ambigious 
    //const int x = mt; //ERROR ambigious
}

为什么允许编译转换运算符的不同版本(基于常量)是有意义的,因为它们的使用总是会导致歧义?

有人可以澄清我在这里缺少什么吗?

【问题讨论】:

  • 一个猜测:没有人足够关心列出稍微有用和完全无用的案例,因此标准中没有关于此的规则。例如,将其设为const int() volatile 可能会使它再次有用。也许吧。
  • 没有禁止无用声明的规则。试图排除所有无用的结构对于语言设计来说是一个非常糟糕的策略。
  • @curiousguy 编译器对仅返回类型不同的函数抛出错误。这只是该场景的特例。所以应该出错
  • @code707 根据定义,函数不能仅在返回类型上有所不同,编译器会因为同一函数的两个不同声明而抱怨。

标签: c++ c++11 type-conversion constants language-lawyer


【解决方案1】:

对于转换,它们是模棱两可的;但你可以明确地调用它们。例如

int x = mt.operator int();
const int x = mt.operator const int();

【讨论】:

  • 您知道在哪些情况下这可能有意义吗?
  • 在现实世界中,我想不出来。
  • 可能是为了绑定成员函数指针?我手头没有语法...
  • 我认为它应该在标准中被禁止
  • 请随意写一份提案,列出此处不允许使用const-qualified 的类型,或者说明为什么没有类型(甚至是复杂的用户定义的类型)可能是const-qualified .显然没有其他人对此有足够强烈的感觉来完成这项工作,但你可能是那个人!
【解决方案2】:

我相信从最严格的意义上说,即使它对const 没有多大意义,这也是合法的。

函数声明和函数类型是有区别的,它们没有相同的约束。

函数声明 可能仅在它们的返回类型或(C++17 起)异常规范上没有区别。但是,关于函数 type 并没有这样的说法(据我所知)。

标准 [class.conv.fct] 将转换函数描述为具有这样那样的形式(列出了三种替代方案),所有这些看起来都不像正常的函数声明,特别是它们很明显没有返回类型。

声明,函数类型是“不带参数返回转换类型ID的函数”,但没有提到转换函数声明 有任何诸如返回类型之类的东西。相反,很明显列出的三种替代形式没有返回类型。

由于转换函数没有返回类型(在它们的声明中...),它不会发生冲突。所以,我想,在最严格、最迂腐的意义上,它甚至有点“合法”,不管它是否有意义。

如果您考虑一下,那么它也必须以某种方式合法。一个类很可能有不止一个转换函数到不同的东西(不仅仅是const 不同)。这样的代码确实存在,有时这样做很有意义。
例如,您可能有一个类File,它可以转换为string(文件名)或handle_t(操作系统句柄),以防您想使用包装器的某些操作系统特定或外来函数类不直接支持(想想writevteeepoll?)这当然是你期望的工作!
但是,如果我们将转换函数视为“只是函数”,那么它们只会在返回类型上有所不同,这将导致声明非法。所以……那行不通。

【讨论】:

  • 转换函数没有返回类型——有趣的一点,它教导我们看到转换运算符不只是某种函数,而是像构造函数一样也没有返回类型返回类型但可以用于获取对象。还有一个可以接受的答案:)
【解决方案3】:

当转换运算符的使用总是导致歧义时,为什么允许不同版本(基于常量)的转换运算符(被编译)是有意义的;

这通常没有意义(除了高度人为的用例),编译器可能会警告你:

prog.cc:12:25: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
     operator  const int()
                         ^

【讨论】:

  • 可以添加这样的用例吗?
  • @Wolf 见宋元瑶的回答。用例是为了证明您可以通过单独调用它们来做出改变。这就是为什么我认为高度人工化的原因,它没有真正的用途。
  • 而且因为没有人可能会这样做(出于显而易见的原因),所以引入不允许这样做的措辞更改是没有意义的。无论如何,那是我的 2 美分。
  • 考虑一些模板代码,而不是直接使用 intconst int,您会得到更复杂的类型计算,恰好为某些模板参数输出这些类型。
  • @T.C.也许吧,但是code707的例子并没有引入任何模板的概念。
【解决方案4】:

我得出的结论是,没有明确允许编写仅在返回值的常量上有所不同的对话运算符。编译过程明确禁止它太昂贵

请记住,(成员)函数仅在返回类型上有所不同

class mytest
{
    int f();
    const int f();
};

被禁止:

错误:'const int mytest::f()' 不能重载

只是转换运算符以operator 开头才有所不同。

【讨论】:

  • 类型是转换函数名称的一部分,可以这么说。这实际上并不是两个只有不同返回类型的重载,而是两个不同的函数。
  • @StoryTeller 添加这个作为另一个答案怎么样?到目前为止给出的答案并不令人满意......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-23
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 2017-03-18
  • 2013-06-08
相关资源
最近更新 更多