簡體   English   中英

指向成員變量的指針為 static 成員

[英]Pointer to member variable as static member

這幾天在擺弄一個數據model的project study,有一種適合我需要的反思。 當我使用最新的穩定版本 g++ 運行我的第一個研究時,我在 Visual Studio 19 中失敗了。太糟糕了,因為后者是我的主要平台……

實際上,我嘗試將指向成員變量的指針存儲到另一個 static 成員變量中。 因此,我真的很希望內聯執行此操作(以適應我更大的概念)。

我將失敗的細節減少到以下 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(我以前沒用過)都接受這個。

編譯器資源管理器上的現場演示

我在一個更簡單的先前示例中嘗試了相同的操作,其中我沒有使用任何模板:

#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 抱怨。

編譯器資源管理器上的現場演示

所以,現在我有點不確定。

是否值得報告的 MSVC 錯誤? 還是我在期待一些我不應該依賴的東西?


免責聲明:

當然,我在過去 3 天用谷歌搜索了這個主題,發現了無數關於如何使用成員指針的教程——包括對SO 的回答:C++ 中這個星號 (*) 的含義是什么? — 指向我自己編寫的成員的指針。 也許,我錯過了 essential 關鍵字,但我 promise 我真的很努力。


以防萬一,您想知道我要做什么……

作為coliru 上的 Live Demo的實際項目研究,我從中制作了上面的 MCVE。


更新:

經過長時間的討論,@doug 幫助我發現這似乎是 Visual Studio 屬性設置的主題。 通過一個干凈啟動的項目,我在本地 VS 2019 中運行了上述所有示例。(之前,我像往常一樣使用 CMake 生成的項目。)我將比較兩個 resp 的選項。 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-(符合標准)

為編譯器指定標准一致性模式。 使用此選項可幫助您識別和修復代碼中的一致性問題,使其更正確、更可移植。

這正是我想要的:符合標准且便攜

在我的 CMake 生成的項目中調整這個選項,我也編譯並運行了它。

Compiler Explorer 上的演示已正確編譯(具有足夠的命令行參數):

編譯器資源管理器上的現場演示

編譯器資源管理器上的現場演示

甚至是最初的研究(我的麻煩從哪里開始):

編譯器資源管理器上的現場演示


我想知道的是:當我編寫 CMake 腳本時,我已經使用了

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

確切的意圖是符合標准和便攜

所以,似乎我必須在 CMake 中設置其他東西。(最后的手段可能是特定於平台的設置,但如果可能的話我會調查尋找其他東西。)


關於我的問題,我發現
CMake 問題 #17068:
MSVC 工具集 14.1+:設置 /permissive- 當 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 解決方案/項目編譯的代碼也沒有任何投訴。

@Scheff 已確定一個問題可能會影響其他人重新內聯 static 成員初始化。 它特別有問題,因為它以不同方式影響編譯器資源管理器 c++17 默認值 v MSVC IDE c++17 默認值。 看他的回答和分析:

為不允許內聯 static 成員的 MSVC 使用默認的 c++ 設置 (c++14)。

將設置更改為 c++17 或更高。 這是在同一行內聯 static 初始化的常見原因。

然而,經過聊天,結果發現 c++17 正在使用,但不同之處在於它與 CMake 一起使用。顯然 CMake 和 MSBuild 解決方案/項目文件之間存在差異。 后者有效,前者無效。 正在調查中,並將更新結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM