为啥不使用强制转换语法调用“operator void”?

Posted

技术标签:

【中文标题】为啥不使用强制转换语法调用“operator void”?【英文标题】:Why is "operator void" not invoked with cast syntax?为什么不使用强制转换语法调用“operator void”? 【发布时间】:2011-05-01 04:21:11 【问题描述】:

在玩user GMan 的this answer 时,我制作了以下sn-p(用Visual C++ 9 编译):

 class Class 
 public:
     operator void() 
 ;

 Class object;
 static_cast<void>( object );
 (void)object;
 object.operator void();

在使用调试器后,我发现转换为void 不会调用Class::operator void(),只有第三次调用(显式调用运算符)实际上调用了运算符,这两个强制转换什么都不做。

为什么operator void 不使用强制转换语法调用?

【问题讨论】:

我喜欢你总是问奇怪但有趣的问题;)这是我的 +1。 您希望在没有演员的情况下执行什么代码?实际上没有...为什么要改变这个? @Eiko:如果那是operator int() 而我写了(int)object;,那么operator int() 将被调用。原来operator void() 不是这种情况,所以我问了这个问题。 对于它的价值,Comeau 给出了以下警告:“Class::operator void()”将不会被调用以进行隐式或显式转换”。 和 gcc 警告:conversion to void will never use a type conversion operator 【参考方案1】:

技术原因见 §12.3.2:

转换函数永远不会用于将(可能是 cv 限定的)对象转换为(可能是 cv 限定的)相同的对象类型(或对它的引用),转换为该对象的(可能是 cv 限定的)基类类型(或对它的引用),或(可能是 cv 限定的)void

理由是(可能)允许 §5.2.9/4 起作用:

任何表达式都可以显式转换为“cv void”类型。表达式值被丢弃。

(void)expr 假设对 any 表达式的结果值不做任何事情,但如果它调用您的转换运算符,它不会丢弃任何东西。所以他们禁止在转换中使用operator void


为什么不让转换类型 ID 为 void 的格式不正确呢?谁知道呢,但请记住,它并非完全没用:

struct foo

    operator void()
    
        std::cout << "huh?" << std::endl;
    

;

typedef void (foo::*void_function)();

foo f;
void_function func = &foo::operator void;

(f.*func)(); // prints "huh"
f.operator void(); // also does (which you knew)

它在技术上仍然对某些东西有用,所以也许这足以说明它不符合格式。

【讨论】:

“为什么不将转换类型 ID 设置为 void 格式不正确?” 可能是因为 void 可能隐藏在 typedef 或模板参数? @dyp,这就是 not ill-formed 的问题:意外行为:您希望转换运算符转换,但这个永远不会那样做。使其格式错误将有助于假定模板库的开发人员及早发现错误。但是,至少现在编译器会针对这种情况发出警告。 @GreenScape 有些用例你不关心它不会被调用,而使用ill-formed,你必须生成特殊情况。就像f(future.get()) 对应future&lt;void&gt; 此外,到void 的标准转换应该胜过任何用户定义的转换。

以上是关于为啥不使用强制转换语法调用“operator void”?的主要内容,如果未能解决你的问题,请参考以下文章

为啥可以从指向实例化基类对象的强制转换指针调用非静态派生类方法?

为啥我可以键入别名函数并在不强制转换的情况下使用它们?

父类对象是不是可以强制转换成子类的对象?为啥?

为啥不能将不完整的类型强制转换为 void?

Java:父类对象为啥能转换成子类对象

为啥我们在调用 bind() 时将 sockaddr_in 转换为 sockaddr?