【问题标题】:Is it legal to cast a forward-declared type to void? [duplicate]将前向声明的类型强制转换为无效是否合法? [复制]
【发布时间】:2018-09-11 18:01:07
【问题描述】:

下面是一个 C++ 头文件,在 g++ 和 clang 下编译没有错误,但在 MSVC2015 下,它在(void) copyFrom 行出错,错误为C2027: use of undefined type 'blah::SomeOtherClass'

我的问题是:根据 C++ 标准,这段代码合法吗?或者如果代码不正确(即因为合法地将参数强制转换为 (void) 需要的不仅仅是前向声明),那么在不引入不需要的 @ 参数的情况下保留我的 copyFrom 参数的 DOxygen 文档的好方法是什么? 987654325@ 警告进入我的编译器输出? (请注意,此时SomeOtherClass 的完整定义不可用,因为SomeOtherClass 依赖于DummyImplementation

#ifndef blah_h
#define blah_h

namespace blah {

class SomeOtherClass;

/** Example of the problem at hand */
class DummyImplementation
{
public:
   /** Dummy implemention of CopyFrom().
    *  @param copyFrom This parameter is ignored.
    *  @returns zero.
    */
   int CopyFrom(const SomeOtherClass & copyFrom)
   {
      (void) copyFrom;  // error C2027: use of undefined type 'blah::SomeOtherClass'
      return 0;
   }
};

} // end namespace blah

#endif

更新:根据 Francois 的要求,这是我的程序在使用 MSVC 19.0.24210.0 构建时使用的构建(并不是关于 C++ 标准要求的问题的答案应该取决于特定版本的 MSVC 的行为) :

cl -c -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline /nologo /MP 
/arch:SSE2 /Zi -O2 -MD -Zc:strictStrings -GR -W3 -w34100 -w34189 -w44996 
-EHsc -D_WIN32_WINNT=0x0601 -DNDEBUG -D__WIN32__ -D_USE_MATH_DEFINES 
-DQT_NO_CAST_ASCII -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB
[... various -I flags omitted ...]

【问题讨论】:

  • 这不会产生带有 gcc 7 或 cland 6 的程序集,也不会产生错误消息。它还可以在 Visual Studio 2015 中正常编译。请阅读 minimal reproducible examples 并指定哪个编译器、哪个编译器版本和哪些编译器标志会产生您观察到的结果。
  • 在这种情况下,我认为应该没问题,因为:Any expression can be explicitly converted to type “cv void.” The expression value is discarded.... 所以理论上你并没有真正使用/引用变量 copyFrom。但是,严格来说,它不应该被允许在你的实现中引用一个前向声明的类型变量......我想这个特殊情况取决于编译器!? - 它是先“取消”表达式还是先检查不完整类型的用法?
  • 不完全清楚这是否会触发左值到右值的转换,这需要完整的类型。当您想强制读取 volatile 变量并丢弃结果时,相当痛苦,在某些编译器上 (void)vvar; 就足够了,在其他编译器上您必须编写 (void)+vvar;
  • 您指的是doxygen 的哪个版本?你想写int CopyFrom(const SomeOtherClass & )吗?否则还要更清楚地说明doxygen 问题。
  • 你可以试试std::addressof(copyFrom)

标签: c++ visual-c++ language-lawyer doxygen forward-declaration


【解决方案1】:

全文请参考this答案。

根据cppref,对于(type-name) expression(强调我的)

如果type-namevoid,则评估expression 的副作用并丢弃其返回值,与单独使用expression 时相同,如表达式语句。

也就是说,(void)copyFrom 等价于 copyFrom,它没有任何作用,并且在 C++ 中不需要完整的类型。

顺便说一句,您的代码可以使用 MSVC 2017 (live) 正常编译。

要抑制编译器警告,您可以考虑:

std::addressof(copyFrom)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-17
    • 1970-01-01
    • 2021-03-08
    • 1970-01-01
    • 2012-08-29
    • 2018-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多