Почему поле внутри локального класса не может быть статичным?
void foo (int x)
{
struct A { static const int d = 0; }; // error
}
Помимо ссылки из стандарта, есть ли мотивация этого запретить static
поле внутри внутреннего класса?
error: field `foo(int)::A::d' in local class cannot be static
Редактировать: Однако static
функции-члены разрешены. У меня есть один вариант использования для такого сценария. Предположим, я хочу foo()
быть вызванным только для POD, тогда я могу реализовать это как,
template<typename T>
void foo (T x)
{
struct A { static const T d = 0; }; // many compilers allow double, float etc.
}
foo()
должен пройти только для POD (если static
разрешено), а не для других типов данных. Это только один случай использования, который приходит мне в голову.
5 ответов
Я думаю, это потому, что статические члены класса должны быть определены в глобальной области видимости.
Редактировать:
Извините за то, что я бездельник и просто выбрасываю вещи:) Чтобы быть немного более точным. Статические члены класса должны быть определены в глобальной области видимости, например
foo.h
class A {
static int dude;
};
foo.cpp
int A::dude = 314;
Теперь, поскольку область видимости внутри void foo(int x) не является глобальной, нет области для определения статического члена. Надеюсь, это было немного яснее.
Магнус Ског дал реальный ответ: статический член данных - это просто декларация; объект должен быть определен в другом месте, в области пространства имен, а определение класса не отображается в области пространства имен.
Обратите внимание, что это ограничение относится только к статическим элементам данных. Это означает, что существует простой обходной путь:
class Local
{
static int& static_i()
{
static int value;
return value;
}
};
Это предоставляет вам точно такую же функциональность за счет использования синтаксиса функции для доступа к нему.
Потому что никто не видел в этом необходимости?
[edit]: статические переменные должны быть определены только один раз, как правило, за пределами класса (кроме встроенных). Разрешение их внутри локального класса потребовало бы разработки способа их определения. [/редактировать]
Любая функция, добавленная к языку, имеет цену:
- это должно быть реализовано компилятором
- он должен поддерживаться в компиляторе (и может содержать ошибки, даже в других функциях)
- он живет в компиляторе (и, следовательно, может вызвать некоторое замедление, даже если он не используется)
Иногда нереализация функции является правильным решением.
Локальные функции и классы уже добавляют языку трудности, принося мало пользы: их можно избежать с помощью static
функции и безымянные пространства имен.
Честно говоря, если бы мне пришлось принять решение, я бы полностью их убрал: они просто загромождают грамматику.
Единственный пример: самый мучительный разбор.
Я думаю, что это та же проблема именования, которая помешала нам использовать локальные типы в экземплярах шаблонов.
Имя foo()::A::d
не является хорошим именем для компоновщика, так как он должен найти определение статического члена? Что если в функции baz() есть другая структура A?
Интересный вопрос, но мне трудно понять, почему вы хотите статический член в локальном классе. Статика обычно используется для поддержания состояния во время выполнения программы, но в этом случае не лучше ли использовать статическую переменную, область действия которой была foo()
?
Если бы мне пришлось угадывать, почему существует такое ограничение, я бы сказал, что это связано с трудностями, с которыми сталкивается компилятор, зная, когда выполнять статическую инициализацию. Документы по стандартам C++ могут предоставить более формальное обоснование.
Просто так.
В C++ раздражает то, что существует сильная зависимость от концепции "глобального контекста", где все должно иметь однозначное имя. Даже механизм вложенных пространств имен - это просто обман со строками.
Я полагаю (просто безумное предположение), что одна серьезная техническая проблема связана с компоновщиками, которые были разработаны для C и которые только что получили некоторую настройку, чтобы заставить их работать с C++ (а код C++ требует взаимодействия с C).
Было бы неплохо получить любой код C++ и "обернуть его", чтобы использовать его без конфликтов в более крупном проекте, но это не так из-за проблем с компоновкой. Я не думаю, что есть какие-то разумные философские основания для запрета статики или не встроенных методов (или даже вложенных функций) на уровне функций, но это то, что мы получили (на данный момент).
Даже двойственность декларации / определения со всей ее досадной многословностью и последствиями связана только с проблемами реализации (и для того, чтобы дать возможность продавать пригодный для использования объектный код без предоставления исходного кода, что сейчас намного менее популярно по уважительным причинам).