इन दिनों मैं एक डेटा मॉडल के लिए एक परियोजना अध्ययन के साथ काम कर रहा था जिसमें मेरी आवश्यकताओं के लिए उपयुक्त प्रतिबिंब था। जबकि मैंने अपना पहला अध्ययन जी ++ के हालिया स्थिर संस्करण के साथ चल रहा था, मैं विजुअल स्टूडियो 19 में असफल रहा। बहुत बुरा, क्योंकि बाद वाला मेरा प्राथमिक मंच है ...

प्रभावी रूप से, मैं एक पॉइंटर को सदस्य चर में किसी अन्य स्थिर सदस्य चर में संग्रहीत करने का प्रयास करता हूं। इस प्रकार, मेरे लिए यह इनलाइन करना वास्तव में वांछनीय है (मेरी बड़ी अवधारणा में फिट होने के लिए)।

मैंने असफल विवरण को निम्नलिखित एमसीवीई में घटा दिया:

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;
}

हैरान है कि यह जी ++ में काम करता है लेकिन एमएसवीसी में नहीं, मैंने कंपाइलर एक्सप्लोरर पर एक नज़र डाली थी कि अन्य कंपाइलर्स इस बारे में क्या कहते हैं। इसलिए, मैंने पाया कि हालिया क्लैंग और यहां तक ​​कि हालिया आईसीसी (मैंने पहले कभी इसका इस्तेमाल नहीं किया) इसे स्वीकार करते हैं।

कंपाइलर एक्सप्लोरर पर लाइव डेमो

मैंने इसे और भी सरल पिछले उदाहरण के साथ करने की कोशिश की जहां मैंने किसी भी टेम्पलेट का उपयोग नहीं किया:

#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');
}

नतीजा वही है: जी ++, क्लैंग, और आईसीसी इस जुर्माना को संकलित करता है लेकिन एमएसवीसी शिकायत करता है।

कंपाइलर एक्सप्लोरर पर लाइव डेमो

तो, अब मैं थोड़ा अनिश्चित हूँ।

क्या यह एमएसवीसी की एक बग है जिसे रिपोर्ट किया जा सकता है? या क्या मैं किसी ऐसी चीज की उम्मीद कर रहा हूं जिस पर मुझे भरोसा नहीं करना चाहिए?


अस्वीकरण:

बेशक, मैंने पिछले 3 दिनों में इस विषय पर गुगली की और सदस्य सूचक का उपयोग करने के तरीके के बारे में लाखों ट्यूटोरियल पाया - जिसमें SO का उत्तर भी शामिल है: C++ में इस स्टार (*) चिन्ह का क्या अर्थ है? — पॉइंटर टू मेम्बर मैंने खुद लिखा है। हो सकता है, मुझे आवश्यक कीवर्ड याद आ रहा था लेकिन मैं वादा करता हूं कि मैंने वास्तव में कड़ी मेहनत की है।


मामले में, आप सोच रहे हैं कि मैं क्या करने की कोशिश कर रहा हूँ ...

वास्तविक परियोजना अध्ययन कोलिरू पर लाइव डेमो के रूप में जिसमें से मैंने अपना उपरोक्त एमसीवीई बनाया है।


अपडेट करें:

एक लंबी चर्चा के बाद, @doug ने मुझे यह पता लगाने में मदद की कि यह विजुअल स्टूडियो संपत्ति सेटिंग्स का विषय प्रतीत होता है। एक साफ-सुथरी परियोजना के साथ, मुझे अपने स्थानीय वीएस 2019 में उपरोक्त सभी नमूने चल रहे हैं। (इससे पहले, मैंने हमेशा की तरह सीएमके-जनित परियोजनाओं का उपयोग किया था।) मैं दो सम्मान के विकल्पों की तुलना करूंगा। वीएस महत्वपूर्ण अंतर का पता लगाने के लिए प्रोजेक्ट करता है और अगर मुझे कुछ मिला तो अपडेट पोस्ट करें ...

2
Scheff's Cat 25 अक्टूबर 2020, 20:02

2 जवाब

सबसे बढ़िया उत्तर

@doug ने मुझे संकेत दिया कि उसने बिना किसी शिकायत के मेरा कोड VS 2019 में चलाया।

एक लंबी बातचीत के बाद, उन्होंने मुझे एक नए बनाए गए वीएस समाधान में मेरे उपरोक्त नमूनों का परीक्षण करने का संकेत दिया। मुझे केवल C++17 (/std:c++17) को सक्षम करना था और फिर MSCV ने बिना किसी शिकायत के सभी नमूनों को संकलित किया।

मुझे यह स्वीकार करना होगा कि मैं आमतौर पर वीएस समाधान तैयार करने के लिए सीएमके का उपयोग करता हूं:

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})

इसलिए, मुझे वीएस परियोजना सेटिंग्स में प्रासंगिक अंतर खोजना पड़ा। आखिरकार मैंने ढूंढ लिया:

  • वीएस निर्मित परियोजना में शामिल हैं /permissive-
  • सीएमके निर्मित परियोजना नहीं है।

प्रोजेक्ट सेटिंग्स में, यह है

- C/C++
  - Language
    - Standards conformance: Yes (/permissive)

एमएस ऑनलाइन डॉक्टर:

/ अनुमेय- (मानक अनुरूपता)

कंपाइलर के लिए मानक अनुरूपता मोड निर्दिष्ट करें। इस विकल्प का उपयोग अपने कोड में अनुरूपता समस्याओं की पहचान करने और उन्हें ठीक करने में मदद करने के लिए करें, ताकि इसे अधिक सही और अधिक पोर्टेबल दोनों बनाया जा सके।

मैं ठीक यही चाहता हूं: मानक अनुरूप और पोर्टेबल होना

मेरे सीएमके जेनरेट प्रोजेक्ट में इस विकल्प को समायोजित करते हुए, मैंने इसे संकलित किया और साथ ही चल रहा था।

कंपाइलर एक्सप्लोरर पर डेमो ठीक से संकलित (पर्याप्त कमांड लाइन तर्कों के साथ):

कंपाइलर एक्सप्लोरर पर लाइव डेमो

कंपाइलर एक्सप्लोरर पर लाइव डेमो

और यहां तक ​​कि प्रारंभिक अध्ययन (जहां से मेरी परेशानी शुरू हुई):

कंपाइलर एक्सप्लोरर पर लाइव डेमो


मुझे क्या आश्चर्य है: जब मैंने अपनी सीएमके स्क्रिप्ट लिखी थी तो मैंने पहले ही इस्तेमाल किया था

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

सटीक इरादे से मानक अनुरूप और पोर्टेबल होने के लिए

तो, ऐसा लगता है कि मुझे सीएमके में कुछ और स्थापित करना है। (अंतिम उपाय एक प्लेटफ़ॉर्म-विशिष्ट सेटिंग हो सकता है लेकिन यदि संभव हो तो मैं कुछ और खोजने के लिए जाँच करूँगा।)


अपनी समस्या के बारे में, मैंने पाया
सीएमके अंक #17068:
MSVC टूलसेट 14.1+: सेट /अनुमोदक- CXX_EXTENSIONS==बंद कब?


एक कंपाइलर विशिष्ट विकल्प के साथ मेरी सीएमके स्क्रिप्ट तय करने के बाद:

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (MSVC)
  add_compile_options(/permissive-)
endif()

और मेरे वीएस समाधान/परियोजनाओं को फिर से बिना किसी शिकायत के संकलित कोड उत्पन्न किया।

3
Scheff's Cat 26 अक्टूबर 2020, 10:32

@Scheff ने एक ऐसी समस्या की पहचान की है जो अन्य लोगों को फिर से इनलाइन स्थिर सदस्य आरंभीकरण को प्रभावित करने की संभावना है। यह विशेष रूप से समस्याग्रस्त है क्योंकि यह कंपाइलर एक्सप्लोरर c++17 डिफॉल्ट्स v MSVC IDE c++17 डिफॉल्ट्स को अलग तरह से प्रभावित करता है। उनका उत्तर और विश्लेषण देखें:

MSVC के लिए डिफ़ॉल्ट c++ सेटिंग्स (c++14) का उपयोग करना जो इनलाइन स्थिर सदस्यों को अनुमति नहीं देता है।

सेटिंग को c++17 या उच्चतर में बदलें। यह एक ही लाइन पर इनलाइन स्थैतिक आरंभीकरण का सामान्य कारण है।

हालाँकि, चैट के बाद, यह पता चला कि c ++ 17 का उपयोग किया जा रहा है, लेकिन अंतर यह है कि इसका उपयोग CMake के साथ किया जा रहा है। स्पष्ट रूप से सीएमके और एमएसबिल्ड समाधान/प्रोजेक्ट फ़ाइल के बीच एक अंतर है। उत्तरार्द्ध काम करता है, पूर्व नहीं करता है। जांच के तहत और परिणामों के साथ अद्यतन करेंगे।

1
doug 25 अक्टूबर 2020, 22:22