sizeof при статической инициализации константного члена - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть такой код:

class A
{
public:

    unsigned long a;
    static const unsigned long b = sizeof(a); // "error C2327: 'A::a' : is not a type name, static, or enumerator" in VC++
};

Я получил ошибку компилятора в VC ++ и никаких ошибок в IAR.Какой компилятор прав, что говорит C ++ об этом?

Ответы [ 4 ]

0 голосов
/ 28 ноября 2018

static const -квалифицированные инициализаторы класса в классе, использующие не static члены, не входили в стандарт C ++ до C ++ 11.

Самый ранний компилятор MSVC, который полностью поддерживает C++ 11 - это MSVC2017.

Этот компилятор правильно скомпилирует ваш код.

0 голосов
/ 28 ноября 2018

Ваши версии MSVS довольно старые, поэтому, основываясь на этом, и если они по умолчанию используют C ++ 03, они корректны, чтобы отклонить ваш код.Я процитирую n1905 , что для наших целей очень близко к стандарту C ++ 03.

9.4 [class.static] (выделениемой)

Если неквалифицированный идентификатор (5.1) используется в определении статического члена после идентификатора объявления члена, и поиск имени (3.4.1) обнаруживает, что неквалифицированный идентификатор относится к статическомучлен, перечислитель или вложенный тип класса члена (или базового класса класса члена), неквалифицированный идентификатор преобразуется в выражение квалифицированного идентификатора, в котором спецификатор вложенного имени называет область действия класса, из которойчлен ссылается. Определение статического члена не должно напрямую использовать имена нестатических членов его класса или базового класса его класса (в том числе в качестве операндов оператора sizeof).Определение статического члена может ссылаться на эти члены только для формирования указателя на члены (5.3.1) или с синтаксисом доступа к членам класса (5.2.5).

0 голосов
/ 28 ноября 2018

Ответ StoryTeller указывает, почему это не сработало на .А именно потому, что он не был поддержан до .

Насколько это не полностью совместимый.Но я проверил, что этот код работает вокруг недостатка:

static const unsigned long b = sizeof(decltype(a))

Если вы хотите что-то, что будет работать и с , рассмотрите возможность сделать b aглобальный, вместо статического члена A:

const unsigned long b = sizeof(A().a)
0 голосов
/ 28 ноября 2018

Что у вас есть?

У вас есть определение class с именем A.

Ваш класс имеет a unsigned long с именем a.

Ваш класс имеет a static const unsigned long с именем b.

В некоторых компиляторах C ++ static и нестатические члены class нельзя смешивать, особенно на этапе определения.

Что вы хотите?

static const unsigned long b = sizeof(unsigned long);

Это не совсем то, что вы хотите, но именно так умный компилятор пытается выяснить.

ПОЧЕМУ ???

Потому что статические члены не ограничивают свою область определением объекта.Они выходят за рамки объекта и доступны из любого места, просто выводя A::b в консоль, используя, например, std::cout << A::b << std::endl.

Clang не принимает эту конструкцию, GCC принимает (оба с -g -std=c++98)

MSVC 19.14 (Visual Studio 15.7) тоже не принимает его, но Visual Studio 15.8 с MSVC 19.15 делает.

Тщательно выбирайте.

Где я проверяювсе это?

Здесь я проверяю множество компиляторов: https://godbolt.org/ Это один из методов, но в будущем вы должны избегать такого рода хаков.

Магический код для проверкии вина

Часть обвинения предназначена для смешивания C и C ++.Это только для компиляции со старыми версиями без каких-либо проверок:

#include <stdio.h>

class A
{
public:

    unsigned long a;
    static const unsigned long b = sizeof(a); // "error C2327: 'A::a' : is not a type name, static, or enumerator" in VC++
};

int main (void)
{
    printf ( "Hello World" ); // I strongly not recommend using printf's in C++ code. 
    printf ( "%d", A::b );    // This is only to fill a functional example, not a rightful one.
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...