Calling function type alias instead of function

124 Views Asked by At

Consider the following code:

#include <iostream>

using f = void(std::string);

void fcorrect(f func, std::string s) {
    func(s); // calling function
};

void fmistake(f func, std::string s) {
    f(s); // calling type alias instead of function
};

void myprint(std::string s) {
    std::cout << s << std::endl;
};

int main() {
    std::string s = "message";
    fcorrect(myprint, s);
    fmistake(myprint, s);
    return 0;
}

Function fcorrect receives myprint function and a string as arguments and prints this string as expected. Function fmistake contains a deliberate mistake - it calls type alias f instead of function func. It prints nothing.

I wonder what's happening under the hood when the latter function call takes place? Namely, why no compile time or runtime error are thrown?

1

There are 1 best solutions below

1
Jan Schultke On BEST ANSWER

As stated by commenters, f(s) is a declaration. The crucial wording is here:

There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is considered a declaration, except as specified below.

[ Example 2:

class T { /* [...] */ };
// [...]
T(a);   //  declaration
// [...]

-- end example ]

- [stmt.ambig] p1

It doesn't matter what the type is (class, function, etc.), T(a) is a declaration if T names a type.

The declaration f(s) does nothing here because it is not used, and is equivalent to f s or void s(std::string). s is already a function parameter std::string s in this context, so GCC is wrong about allowing it. GCC also allows:

void fmistake(f func, std::string s) {
    void s(std::string);
}

// GCC also allows the following (in C++ mode)
void foo(int x) {
    // GCC rejects this as re-declaring a symbol in C, but not in C++ mode.
    void x(int);
}

This is a known GCC bug 52953, and has first been reported in 2012.