Какие ограничения ISO C++03 накладывает на структуры, определенные в области видимости функции?

Нам не разрешается определять структуру функтора внутри функции, потому что нельзя использовать функции, объявленные структурами, в экземплярах шаблонов функций.

Есть ли какие-либо другие существенные подводные камни, о которых следует знать? Например, это было бы плохо:

int foo()
{
    struct Scratch
    {
        int a, b, c;
    };
    std::vector<Scratch> workingBuffer;
    //Blah Blah
}

5 ответов

Решение

1. Стандарт C++ запрещает использование локально определенных классов с шаблонами.

14.3.1 / 2: Локальный тип, тип без связи, безымянный тип или тип, составленный из любого из этих типов, не должны использоваться в качестве аргумента шаблона для параметра типа шаблона.

Пример кода:

    template <class T> class X { /* ... */ };
    void f()
    {
      struct S { /* ... */ };
      X<S> x3;  // error: local type used as
                //  template-argument
      X<S*> x4; // error: pointer to local type
                //  used as template-argument
    }

Вот еще немного ссылок из документации IBM:

2. Объявления в локальном классе могут использовать только имена типов, перечисления, статические переменные из окружающей области, а также внешние переменные и функции.

Пример кода:

int x;                         // global variable
void f()                       // function definition
{
      static int y;            // static variable y can be used by
                               // local class
      int x;                   // auto variable x cannot be used by
                               // local class
      extern int g();          // extern function g can be used by
                               // local class

      class local              // local class
      {
            int g() { return x; }      // error, local variable x
                                       // cannot be used by g
            int h() { return y; }      // valid,static variable y
            int k() { return ::x; }    // valid, global x
            int l() { return g(); }    // valid, extern function g
      };
}

int main()
{
      local* z;                // error: the class local is not visible
      return 0;
}

3. Локальный класс не может иметь статических членов данных

Пример кода:

void f()
{
    class local
    {
       int f();              // error, local class has noninline
                             // member function
       int g() {return 0;}   // valid, inline member function
       static int a;         // error, static is not allowed for
                             // local class
       int b;                // valid, nonstatic variable
    };
}

Область действия локальных классов - это функция, в которой они определены. Но это само по себе неинтересно 1.

Что делает локальные классы интересными, так это то, что если они реализуют некоторый интерфейс, вы можете создавать его экземпляры (используя new ) и вернуть их, тем самым делая реализацию доступной через указатель базового класса даже вне функции.

Некоторые другие факты о местных классах:

  • Они не могут определять статические переменные-члены.

  • Они не могут получить доступ к нестатическим "автоматическим" локальным переменным функции включения. Но они могут получить доступ к static переменные.

  • Их можно использовать в шаблонных функциях. Однако их нельзя использовать в качестве аргумента шаблона.

  • Если они определены внутри функции шаблона, то они могут использовать параметры шаблона функции включения.

  • Локальные классы являются окончательными, это означает, что пользователи вне функции не могут наследовать локальный класс от функции. Без локальных классов вам пришлось бы добавить безымянное пространство имен в отдельном модуле перевода.

  • Локальные классы используются для создания функций батута, обычно известных как thunks.

Некоторые ссылки из Стандарта (2003)

9.8 Локальные объявления классов [class.local]

\ 1. Класс может быть определен в определении функции; такой класс называется локальным классом. Имя локального класса является локальным по отношению к окружающей его области. Локальный класс находится в области действия охватывающей области и имеет такой же доступ к именам вне функции, что и функция включения. Объявления в локальном классе могут использовать только имена типов, статические переменные, внешние переменные и функции и перечислители из окружающей области.

[Example:

int x;
void f()
{
   static int s ;
   int x;
   extern int g();

   struct local {
      int g() { return x; } // error: x is auto
      int h() { return s; } // OK
      int k() { return ::x; } // OK
      int l() { return g(); } // OK
   };
// ...
}
local* p = 0; // error: local not in scope

—end example]

\ 2. Функция включения не имеет специального доступа к членам локального класса; он подчиняется обычным правилам доступа (пункт 11). Функции-члены локального класса должны быть определены в пределах их определения класса, если они определены вообще.

\ 3. Если класс X является локальным классом, вложенный класс Y может быть объявлен в классе X и позже определен в определении класса X или позже определен в той же области видимости, что и определение класса X. Класс, вложенный в локальный класс, является местный класс.

\ 4. Локальный класс не должен иметь статических членов данных.

Локальные структуры / классы не могут иметь статические члены-данные, только статические функции-члены. Кроме того, они не могут быть шаблонами.

Локальные структуры совершенно законны, даже в C++98. Вы не можете использовать их с шаблонами в C++ 98, тогда как вы можете использовать в C++0x. G ++ 4.5 поддерживает использование локальных структур с шаблонами в режиме -std= C++0x.

Да. Локальные классы не могут использоваться в качестве параметров шаблона в C++03

Другие вопросы по тегам