Why can I define structures and classes within a function in C++?

C++Data StructuresFunctional Programming

C++ Problem Overview


I just mistakenly did something like this in C++, and it works. Why can I do this?

int main(int argc, char** argv) {
    struct MyStruct
    {
      int somevalue;
    };

    MyStruct s;
    s.somevalue = 5;
}

Now after doing this, I kind of remembered reading about this trick someplace, a long time ago, as a kind of poor-man's functional programming tool for C++, but I can't remember why this is valid, or where I read it.

Answers to either question are welcome!

Note: Although when writing the question I didn't get any references to this question, the current side-bar points it out so I'll put it here for reference, either way the question is different but might be useful.

C++ Solutions


Solution 1 - C++

[EDIT 18/4/2013]: Happily, the restriction mentioned below has been lifted in C++11, so locally defined classes are useful after all! Thanks to commenter bamboon.

The ability to define classes locally would make creating custom functors (classes with an operator()(), e.g. comparison functions for passing to std::sort() or "loop bodies" to be used with std::for_each()) much more convenient.

Unfortunately, C++ forbids using locally-defined classes with templates, as they have no linkage. Since most applications of functors involve template types that are templated on the functor type, locally defined classes can't be used for this -- you must define them outside the function. :(

[EDIT 1/11/2009]

The relevant quote from the standard is:

> 14.3.1/2: .A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter.

Solution 2 - C++

One application of locally-defined C++ classes is in http://en.wikipedia.org/wiki/Factory_method_pattern">Factory design pattern:


// In some header
class Base
{
public:
virtual ~Base() {}
virtual void DoStuff() = 0;
};




Base* CreateBase( const Param& );




// in some .cpp file
Base* CreateBase( const Params& p )
{
struct Impl: Base
{
virtual void DoStuff() { ... }
};



...
return new Impl;




}


Though you can do the same with anonymous namespace.

Solution 3 - C++

It's actually very useful for doing some stack-based exception-safety work. Or general cleanup from a function with multiple return points. This is often called the RAII (resource acquisition is initialzation) idiom.

void function()
{

    struct Cleaner
    {
        Cleaner()
        {
            // do some initialization code in here
            // maybe start some transaction, or acquire a mutex or something
        }
        
        ~Cleaner()
        {
             // do the associated cleanup
             // (commit your transaction, release your mutex, etc.)
        }
    };

    Cleaner cleaner;
    
    // Now do something really dangerous
    // But you know that even in the case of an uncaught exception, 
    // ~Cleaner will be called.

    // Or alternatively, write some ill-advised code with multiple return points here.
    // No matter where you return from the function ~Cleaner will be called.
}

Solution 4 - C++

Well, basically, why not? A struct in C (going back to the dawn of time) was just a way to declare a record structure. If you want one, why not be able to declare it where you would declare a simple variable?

Once you do that, then remember that a goal of C++ was to be compatible with C if at all possible. So it stayed.

Solution 5 - C++

It's mentioned at, for example, section "7.8: Local classes: classes inside functions" of http://www.icce.rug.nl/documents/cplusplus/cplusplus07.html which calls it a "local class" and says it "can be very useful in advanced applications involving inheritance or templates".

Solution 6 - C++

It's for making arrays of objects that are properly initialized.

I have a class C which has no default constructor. I want an array of objects of class C. I figure out how I want those objects initialized, then derive a class D from C with a static method which provides the argument for the C in D's default constructor:

#include <iostream>
using namespace std;

class C {
public:
  C(int x) : mData(x)  {}
  int method() { return mData; }
  // ...
private:
  int mData;
};

void f() {

  // Here I am in f.  I need an array of 50 C objects starting with C(22)

  class D : public C {
  public:
    D() : C(D::clicker()) {}
  private:
    // I want my C objects to be initialized with consecutive
    // integers, starting at 22.
    static int clicker() { 
      static int current = 22;
      return current++;
    } 
  };

  D array[50] ;

  // Now I will display the object in position 11 to verify it got initialized
  // with the right value.  

  cout << "This should be 33: --> " << array[11].method() << endl;

  cout << "sizodf(C): " << sizeof(C) << endl;
  cout << "sizeof(D): " << sizeof(D) << endl;

  return;

}

int main(int, char **) {
  f();
  return 0;
}

For the sake of simplicity, this example uses a trivial non-default constructor and a case where the values are known at compile time. It is straightforward to extend this technique to cases where you want an array of objects initialized with values that are known only at runtime.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRobert GouldView Question on Stackoverflow
Solution 1 - C++j_random_hackerView Answer on Stackoverflow
Solution 2 - C++Nikolai FetissovView Answer on Stackoverflow
Solution 3 - C++simongView Answer on Stackoverflow
Solution 4 - C++Charlie MartinView Answer on Stackoverflow
Solution 5 - C++ChrisWView Answer on Stackoverflow
Solution 6 - C++Thomas L HoladayView Answer on Stackoverflow