Какие ограничения накладывает ISO C ++ 03 на структуры, определенные в области действия функции? - PullRequest
14 голосов
/ 20 июня 2011

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

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

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

Ответы [ 5 ]

22 голосов
/ 20 июня 2011

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
    };
}
2 голосов
/ 20 июня 2011

Область действия локальных классов - это функция, в которой они определены. Но это само по себе неинтересно 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.Локальный класс не должен иметь статических членов данных.

1 голос
/ 20 июня 2011

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

0 голосов
/ 20 июня 2011

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

0 голосов
/ 20 июня 2011

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

...