2015-03-31 2 views
3

Является ли это gcc слишком приятным и делает то, что разработчик считает, что это будет делать, или clang, чрезмерно суетливый. Я пропускаю некоторые тонкие правила в стандарте, где лязг на самом деле правильно жаловаться на этоClang: error: недействительное использование нестатического элемента данных

Или я должен использовать второй бит кода, который является в основном, как offsetof работает

[[email protected] ~]$ g++ -Wall -pedantic -ansi a.cc 
[[email protected] ~]$ a.out 
50 
[[email protected] ~]$ cat a.cc 
#include <iostream> 

struct Foo 
{ 
    char name[50]; 
}; 

int main(int argc, char *argv[]) 
{ 
    std::cout << sizeof(Foo::name) << std::endl; 
    return 0; 
} 


[[email protected] ~]$ clang++ a.cc 
a.cc:10:29: error: invalid use of non-static data member 'name' 
    std::cout << sizeof(Foo::name) << std::endl; 
         ~~~~~^~~~ 
1 error generated. 
[[email protected] ~]$ g++ -Wall -pedantic -ansi b.cc 
[[email protected] ~]$ a.out 
50 
[[email protected] ~]$ cat b.cc 
#include <iostream> 

struct Foo 
{ 
    char name[50]; 
}; 

int main(int argc, char *argv[]) 
{ 
    std::cout << sizeof(static_cast<Foo*>(0)->name) << std::endl; 
    return 0; 
} 


[[email protected] ~]$ clang++ b.cc 
[[email protected] ~]$ a.out 
50 
+0

Ну, я обнаружил, что добавление -std = C++ 11 перестает жаловаться. Итак, теперь я задаюсь вопросом, какая часть для C++ 98 я нарушаю с этим кодом. Gcc в порядке с ним в любой версии, но это не значит, что я не нарушил правило. – Adrian

+0

Не расширяйте свой вопрос, добавляя комментарии. Либо ответьте на свой вопрос, примите его, задайте новый вопрос. Или отредактируйте свой вопрос, включая заголовок и удаление ненужных частей. – usr1234567

ответ

1

I found adding -std=c++11 stops it complaining. GCC is fine with it in either version.

Современный НКУ версии позволяют это даже в режиме -std=c++98. Однако старые версии, такие как GCC 3.3.6, do жалуются и отказываются компилировать.

So now I wonder which part of C++98 I am violating with this code.

Википедия четко указано, что такая особенность была добавлена ​​в C++ 11, и относится к N2253, который говорит, что синтаксис не считается недействительным стандарта C++ 98 изначально, но потом намеренно разъяснена запретите это (я не знаю, как нестатические поля членов отличаются от других переменных в отношении их типа данных). Некоторое время спустя они решили сделать этот синтаксис действительным, но только до C++ 11.

Сам же документ упоминает некрасивый обходной путь, который также можно увидеть по всей Сети:

sizeof(((Class*) 0)->Field) 

Похоже, просто используя 0, NULL или nullptr может вызвать предупреждения компилятора для возможного разыменования из нулевого указателя (несмотря на то, что sizeof никогда не оценивает свой аргумент), поэтому вместо него может использоваться произвольное ненулевое значение, хотя оно будет выглядеть как интуитивно понятная «магическая константа». Поэтому, на мой C++ изящная слой Деградация я использую:

#if __cplusplus >= 201103L 
    #define CXX_MODERN 2011 
#else 
    #define CXX_LEGACY 1998 
#endif 


#ifdef CXX_MODERN 
    #define CXX_FEATURE_SIZEOF_NONSTATIC 
    #define CxxSizeOf(TYPE, FIELD) (sizeof TYPE::FIELD) 
#else 
    // Use of `nullptr` may trigger warnings. 
    #define CxxSizeOf(TYPE, FIELD) (sizeof (reinterpret_cast<const TYPE*>(1234)->FIELD)) 
#endif 

Примеры использования:

// On block level: 

class SomeHeader { 
public: 

    uint16_t Flags; 

    static CxxConstExpr size_t FixedSize = 
#ifdef CXX_FEATURE_SIZEOF_NONSTATIC 
     (sizeof Flags) 
#else 
     sizeof(uint16_t) 
#endif 
    ; 


}; // end class SomeHeader 



// Inside a function: 

void Foo(void) { 

    size_t nSize = CxxSizeOf(SomeHeader, Flags); 

} // end function Foo(void) 

Кстати, обратите внимание разницу синтаксиса для sizeof(Type) и sizeof Expression, поскольку они формально не то же самое, даже если sizeof(Expression) работает - до тех пор, пока sizeof (Expression) действителен. Итак, самая правильная и переносимая форма будет sizeof(decltype(Expression)), но, к сожалению, она была доступна только в C++ 11; некоторые компиляторы предоставили typeof(Expression) в течение длительного времени, но это никогда не было стандартным расширением.

Смежные вопросы