5

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?

D.R.
  • 20,268
  • 21
  • 102
  • 205
  • I've got a downvote and a close request for this question (off-topic), can anybody maybe tell me why. Is such a question really off-topic on SO? – D.R. Aug 04 '13 at 08:55

2 Answers2

7

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.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • 2
    Thanks, I was guessing something like that. Do you know by chance why VS produces a linker error instead? Which behavior is "standard" and which is "wrong"? – D.R. Aug 03 '13 at 01:08
  • 4
    @D.R.: I think your program has undefined behavior, so both are "correct". Here's the rule: "Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; **no diagnostic required**." – Ben Voigt Aug 03 '13 at 01:10
  • What about this? http://stackoverflow.com/questions/2064692/how-to-print-function-pointers-with-cout – Prashant Kumar Aug 03 '13 at 01:10
  • BenVoigt's comment actually answers the question. The question is not "why my function is being printed as `1`", but "why is it not producing a linker error on gcc". – mfontanini Aug 03 '13 at 01:12
1

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.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720