c++ - 指向成员变量的指针作为静态成员

标签 c++ cmake c++17 visual-studio-2019

这些天来,我正在摆弄一个数据模型的项目研究,该模型具有适合我需要的一种反射。
虽然我的第一项研究使用最近的稳定版 g++ 运行,但我在 Visual Studio 19 中失败了。太糟糕了,因为后者是我的主要平台……
实际上,我尝试将指向成员变量的指针存储到另一个静态成员变量中。因此,我真的很希望内联(以适应我更大的概念)。
我将失败的细节减少到以下 MCVE:

struct Field { };

struct Class {
    
  template <typename CLASS>
  struct BuiltInInfoT {
    Field CLASS::*const pField; // member pointer
  };
  
};

struct Object: Class {
  Field field1;
  static inline BuiltInInfoT<Object> field1BuiltInfo = { &Object::field1 };
};

int main()
{
  Object obj;
}
对这似乎在 g++ 中但在 MSVC 中不起作用感到困惑,我在 Compiler Explorer 上查看了其他编译​​器对此的看法。所以,我发现最近的clang甚至最近的ICC(我以前从未使用过)都接受了这一点。
Live Demo on Compiler Explorer
我在之前没有使用任何模板的更简单的示例中尝试了相同的操作:
#include <iostream>

struct Test {
  struct Info { int Test::*p; };
  int a;
  static inline Info infoA = { &Test::a };
  int b;
  static inline Info infoB = { &Test::b };
  
  Test(int a, int b): a(a), b(b) { }
};

#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__ 

int main()
{
  DEBUG(Test test(123, 456));
  DEBUG(std::cout << (test.*(test.infoA.p)) << '\n');
  DEBUG(std::cout << (test.*(test.infoB.p)) << '\n');
}
结果是一样的:g++、clang 和 ICC 编译得很好,但 MSVC 提示。
Live Demo on Compiler Explorer
所以,现在我有点不确定。
这是一个值得报告的 MSVC 错误吗?还是我期待一些我不应该依赖的东西?

免责声明:
当然,我在过去 3 天里搜索了这个主题,发现了无数关于如何使用成员指针的教程——包括我自己写的 SO: What is the meaning of this star (*) symbol in C++? — Pointer to member 的答案。也许,我错过了基本关键字,但我保证我真的很努力。

以防万一,你想知道我想要做什么......
作为 Live Demo on coliru 的实际项目研究,我从中制作了上面的 MCVE。

更新:
经过长时间的讨论,@doug 帮助我发现这似乎是 Visual Studio 属性设置的主题。通过一个干净启动的项目,我在本地 VS 2019 中运行了上述所有示例。(之前,我照常使用 CMake 生成的项目。)我将比较两个选项。 VS 项目以找出显着差异并在我发现某些内容时发布更新......

最佳答案

@doug 给了我提示,他让我的代码在 VS 2019 中运行,没有任何提示。
经过长时间的交谈,他给了我提示,让我在一个新创建的 VS 解决方案中测试我的上述示例。我所要做的就是启用 C++17 ( /std:c++17 ),然后 MSCV 编译所有示例而没有提示。
我必须承认,我通常使用 CMake 来准备 VS 解决方案:

project (OFM)

cmake_minimum_required(VERSION 3.10.0)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

include_directories("${CMAKE_SOURCE_DIR}")

file(GLOB sources *.cc)
file(GLOB headers *.h)

add_executable(testOFM
  ${sources} ${headers})
因此,我不得不在 VS 项目设置中找到相关的差异。
最后,我找到了它:
  • VS 创建的项目包含 /permissive-
  • CMake 创建的项目没有。

  • 在项目设置中,它是
    - C/C++
      - Language
        - Standards conformance: Yes (/permissive)
    
    MS 在线文档:
    /permissive- (Standards conformance)

    Specify standards conformance mode to the compiler. Use this option to help you identify and fix conformance issues in your code, to make it both more correct and more portable.


    这正是我想要的:符合标准且可移植。
    在我的 CMake 生成项目中调整此选项,我也将其编译并运行。
    Compiler Explorer 上的演示正确编译(使用足够的命令行参数):
    Live Demo on Compiler Explorer
    Live Demo on Compiler Explorer
    甚至最初的研究(我的麻烦开始的地方):
    Live Demo on Compiler Explorer

    我想知道的是:当我编写 CMake 脚本时,我已经使用过
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    set(CMAKE_CXX_EXTENSIONS OFF)
    
    确切的意图是符合标准和便携。
    所以,我似乎还必须在 CMake 中设置其他东西。
    (最后的手段可能是特定于平台的设置,但如果可能的话,我会调查以找到其他东西。)

    关于我的问题,我发现
    CMake Issue #17068:
    MSVC toolset 14.1+: Set /permissive- when CXX_EXTENSIONS==OFF?


    在我使用编译器特定选项修复了我的 CMake 脚本后:
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    set(CMAKE_CXX_EXTENSIONS OFF)
    if (MSVC)
      add_compile_options(/permissive-)
    endif()
    
    并再次生成我的VS解决方案/项目,编译代码也没有任何提示。

    关于c++ - 指向成员变量的指针作为静态成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64526453/

    相关文章:

    c++ - 在全屏模式游戏中运行exe文件

    c++ - Visual Studio 无法识别 __AVX2__ 或 __AVX__

    c++ - 声明从抽象类继承的继承抽象方法是否有任何性能问题?

    c++ - 类 std::result_of 中没有名为 'type' 的类型

    c++ - 使用 CMAKE 调试和发布库链接 (VISUAL STUDIO)

    c++ - 我可以使用 std::pair,但重命名 .first 和 .second 成员名称吗?

    c++ - 将整型数组作为另一个不相关整型类型的数组进行访问的安全且符合标准的方法?

    c++ - 我如何对 condition_variable::wait 周围的包装器进行单元测试?

    c++ - 派生类比基类大,即使它由引用变量组成

    c++ - Clang 10 无法在 macOS 10.12 上将 C++ 应用程序与 CMake 链接