Tuesday, November 13, 2012

Local functions prototyping

A trivial piece of C++ source code:
#include <iostream>

class Foo {
    public:
        Foo(int=5);
};

Foo::Foo(int) {
    std::cout << "[Foo]";
}

int main() {
    Foo Foo0();
    Foo Foo1(1);
    return 0; //SUCCESS?
}
And a trivial question: how many times will the Foo constructor execute?

Explanation:
in the above code, line:
    Foo Foo0();

is not a declaration of a variable named Foo0 of class Foo initialized with default constructor. Instead, it is, what can be called local function prototyping. More precisely, it is a declaration of a new function, named Foo0, which returns result of type Foo.

It seems to be legacy code after nested functions, supported by GCC C Compiler. See the example:
#include <stdio.h>

int main() {
 auto int m_nested();
 int m_nested() {
  return 666;
 }

 printf("%d", m_nested());
 return 0;
}
Function m_nested() is nested within another function (main()), and its scope is limited to that surrounding function.

Getting back to the original code, any attempt to access Foo0 will result in error:
int main() {
    Foo Foo0();
    Foo Foo() { //error: a function-definition is not allowed here before '{' token
        //...
    };
    Foo0(); // error: undefined reference to 'Foo0()'
    Foo0 = *new Foo(); // error: cannot convert 'Foo' to 'Foo()' in assignment
}
The only thing, that would make sense and would actually compile is defining this function somewhere else:
//...
int main() {
    // no access to Foo0() here
    Foo Foo0();
    Foo f = Foo0();
    //.. do some stuff with 'f'
    delete &f;
    return 0;
}

Foo Foo0() {
    std::cout << "Foo0()";
    return *new Foo();
}
Such code will narrow access to Foo0() to the place where it was declared for the first time, and will end as soon as the program leaves the execution block.

No comments:

Post a Comment