Why is Taking the Address of a Function That is Declared Only Working?
Asked Answered
P

2

0

I've asked a question here about whether taking the address of a function forces the compilation of said function specifically with regard to Substitution-Failure-Is-Not-An-Error. The most direct answer to this can be found here:

Informally, an object is odr-used if its address is taken, or a reference is bound to it, and a function is odr-used if a function call to it is made or its address is taken. If an object or a function is odr-used, its definition must exist somewhere in the program; a violation of that is a link-time error.

But all the compilers I've tested show this as perfectly doable:

void foo(int);
auto bar = &foo;

Live Example

This isn't legal is it? But if not, why is it building?

Pl answered 18/7, 2016 at 13:8 Comment(3)
"[basic.def.odr]/4 Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required." Emphasis mine.Soapsuds
Add a line printing content of bar and you should get an error. Generally compilers will not go further than required by Standard and give you an error just because they can. They usually silently compile your code, and then break it in subtle ways after all tests are passed and it is time to ship.Baird
A link-time error is issued if this code is compiled with -O0Nomography
C
5

From [basic.def.odr]:

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

foo is odr-used, but doesn't have a definition (presumably - otherwise the question is moot). The program is ill-formed, but since no diagnostic is required, it's valid to compile.

Typically, it's the linker that catches the lack of definition - not the compiler, since the definition could easily appear in a different translation unit. The canonical example being trying to pass a static const int which lacks a definition into a call to std::max() or std::min().

Corley answered 18/7, 2016 at 13:16 Comment(0)
P
1

Your example is working because the address is never used, so the linker never searches for the symbol.

If you try to print bar, the linking fails.

void foo(int);
auto bar = &foo;
cout << (void*) bar;

http://ideone.com/97Eo6Z

Picul answered 18/7, 2016 at 13:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.