【问题标题】:What restrictions does ISO C++03 place on structs defined at function scope?ISO C++03 对在函数范围内定义的结构有什么限制?
【发布时间】:2011-09-18 22:05:04
【问题描述】:

我们不允许在函数内部定义仿函数结构,因为不允许在函数模板的实例化中使用函数声明的结构。

还有其他需要注意的重大缺陷吗?例如。这会很糟糕吗:

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

【问题讨论】:

  • @Nawaz:我认为这不是完全相同的副本
  • @0A0D:这里提出的这类问题,也已经在该主题中得到了解答。因此可能存在重复。
  • @Billy:在这种情况下,让我从另一个主题复制粘贴我的答案。
  • @Billy:我们是来提供信息的,不符合任意关闭规则。讨论所做的唯一一件事就是走错了方向。与其缩小允许链接的解决方案的范围,不如扩大“答案存在于其他地方”或其他什么的密切原因。由于我相信后者是正确的,并且强迫人们复制和粘贴答案是非常不正确的,所以我投票结束。
  • @GMan:我同意这样的改变。我的问题是,以完全重复的方式关闭听起来像是在谴责——“你这个白痴——在问另一个问题之前你甚至没有寻找解决方案?”。但是,有许多路径会导致基本相同的信息。

标签: c++ c++03


【解决方案1】:

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】:

    本地类的范围是定义它们的函数。但这本身并不有趣1

    本地类的有趣之处在于如果它们实现了某个接口,那么您可以创建它的实例(使用new)并返回它们,从而使实现即使在函数之外也可以通过基类指针访问。

    关于本地类的一些其他事实:

    • 他们不能定义静态成员变量。

    • 他们无法访问封闭函数的非静态“自动”局部变量。但他们可以访问static 变量。

    • 它们可以在模板函数中使用。但是,它们不能用作模板参数

    • 如果他们在模板函数内部定义,那么他们可以使用封闭函数的模板参数。

    • 本地类是最终类,这意味着函数之外的用户不能从本地类派生到函数。如果没有本地类,您必须在单独的翻译单元中添加一个未命名的命名空间。

    • 本地类用于创建trampoline functions,通常称为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 条)。 a的成员函数 本地类应定义在 他们的类定义,如果他们是 完全定义。

    \3。如果类 X 是本地类,则可以在其中声明嵌套类 Y X 类及以后在 X 类或以后的定义 定义在与 X 类的定义。嵌套的类 在本地类中是本地类。

    \4.本地类不应有静态数据成员。

    【讨论】:

      【解决方案3】:

      本地结构/类不能有静态数据成员,只有静态成员函数。此外,它们不能是模板。

      【讨论】:

        【解决方案4】:

        是的。局部类在C++03中不能用作模板参数

        【讨论】:

        • 你有参考吗?我知道您不允许将它们用于函数模板的参数推导——但不一定用于手动实例化类。
        【解决方案5】:

        局部结构是完全合法的,即使在 C++98 中也是如此。但是,您不能在 C++98 中将它们与模板一起使用,而在 C++0x 中则可以。 g++ 4.5 支持在 -std=c++0x 模式下使用带有模板的本地结构。

        【讨论】:

        • 我认为 ideone 使用 c++0x 4.5,但它仍然给本地 template struct ideone.com/5xhWE 报错
        猜你喜欢
        • 2012-06-24
        • 2014-12-20
        • 1970-01-01
        • 1970-01-01
        • 2023-04-06
        • 2020-03-18
        • 2016-01-13
        • 2014-02-25
        相关资源
        最近更新 更多