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.