Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ programming riddle, fun with function pointers

Given the following code snippet:

#include <string>
#include <iostream>

int main()
{
    std::string prefix("->"), middle(), suffix("<-");
    std::cout << "Test: " << prefix << middle << suffix << std::endl;

    return 0;
}

The advanced C++ programmer will immediately see that middle() is not calling std::string's default ctor, instead it's a function declaration.

What's interesting though: Why does gcc produce the following output:

Test: ->1<-

in contrast to Visual Studio's linker error? Does anybody know what's going on here?

like image 425
D.R. Avatar asked Aug 03 '13 01:08

D.R.


2 Answers

A function pointer will be converted to bool when using with cout.

Why the function pointer is not converted to a void * implicitly, which is what operator << overloads on? because function pointers are not object pointers.

C++11 §4.10/2:

A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The result of converting a “pointer to cv T” to a “pointer to cv void” points to the start of the storage location where the object of type T resides, as if the object is a most derived object (1.8) of type T (that is, not a base class subobject). The null pointer value is converted to the null pointer value of the destination type.

like image 59
Yu Hao Avatar answered Sep 19 '22 14:09

Yu Hao


As Yu said, the function pointer is being converted to bool.

The g++ optimizer is evidently pre-evaluating the conversion, while Visual C++ actually generates code to test if the function address is null, which requires the linker to provide the function address.

The rule is that

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.

The function is odr-used because you're using its address. By not providing a definition, you're violating this rule, and the Standard doesn't require a diagnostic, meaning the toolchain is free to do anything it wants.

Visual C++ is generating a diagnostic, although it's not required to.

g++ is giving the actual result of conversion to bool, since it knows that decay of an actual function to a function pointer can never produce a null function pointer.

But formatting your hard drive would be equally valid, since the Standard doesn't say what the toolchain can or can't do here.

like image 41
Ben Voigt Avatar answered Sep 19 '22 14:09

Ben Voigt