12

Is there a way to use function addresses in constant expressions?

void foo()
{}

int main()
{
  static_assert(&foo, "test error");
}

This won't compile.

error C2057: expected constant expression

The intention behind this is that I want to compare two function addresses at compile time.

cooky451
  • 3,460
  • 1
  • 21
  • 39

2 Answers2

6

It is most definitely a compiler bug.

Functions can be used as template argument to template, which means they are const expressions. (See ideone).

Also, the above code compiles fine with gcc 4.6.1, though ideone doesn't compile it, but ideone uses gcc-4.5.1 which has bug with regard to your code.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 4
    I think this might be a little trickier. One of the problems with function addresses is that the compiler does not necessarily *know* it's value (it might be defined in a different translation unit or not defined at all. What is the expected result (at *compile time*) of `&foo` for those cases? (I am not saying that it cannot be done, that expression is considered *odr-use*, so the compiler can assume that it must be defined and let the linker resolve the address is fail if not defined, but I would go to the standard for an authoritative answer to the question. – David Rodríguez - dribeas Mar 04 '12 at 17:31
  • 3
    Functions are known at compile time, but their addresses are not. Symbolic names are used at compile time for the linker to memory-map later. To further complicate things, after templates were introduced in C++, linkers almost universally began folding functions that have identical compiled code. So **two different functions could have the same address at run-time**. The compiler isn't expected to know this. – Drew Dormann Mar 04 '12 at 19:50
  • 1
    Since functions can be relocated at load time (think Windows DLL) then I can't see how `&foo` can be known, in general, until the program is running. – David Heffernan Mar 04 '12 at 20:40
3

This is my understanding, FWIW:

A function type is known a compile time, but a function address is only known at link time. Thus, you can use function types as template parameters, yet addresses are not constant/known at compile time.

In your sample code, the compiler could deduce that the address is nonzero at compile time, but it wouldn't be able to know the specific address then. This is not a compiler bug, though.

Nick
  • 6,808
  • 1
  • 22
  • 34
  • Addresses aren't even known at link time. Code is often be relocated upon loading. – David Heffernan Mar 04 '12 at 20:39
  • 1
    True, but relative addresses within the same loadable module *are* known at link time, so that function jumps can be "wired up". My point is just that the address of the function can be logically taken at run time (ie: the language guarantees this is legal), but not a compile time. – Nick Mar 05 '12 at 04:27