7

I got an official answer to this question that decltype should not trigger function compilation. In fact decltype on a function that is declared but not defined is legal.

Next question, should taking the address of a function trigger the compilation of a function? Take this example:

template <typename T>
void foo(T&& x) { x.func(); }

int main()
{
    auto bar = &foo<int>;
}

All the compilers I've tested fail with an error like:

Request for member func in x, which is of non-class type int

But if I just define foo and don't declare it, the code compiles fine. Can someone provide me with an official source on whether taking the address of a function should require it's compilation?

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 1
    According to http://en.cppreference.com/w/cpp/language/definition%23One_Definition_Rule, "an object is odr-used if its address is taken", and "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". I don't have the relevant standard quotes to make this an answer – KABoissonneault Jul 15 '16 at 17:46
  • @KABoissonneault I'm OK with this. If you can cite http://en.cppreference.com for both of those quotes I'd consider that official enough. – Jonathan Mee Jul 15 '16 at 19:04
  • @KABoissonneault It looks like [what you're citing](http://en.cppreference.com/mwiki/index.php?title=cpp/language/definition&diff=prev&oldid=73909) was written by [Cubbi](http://stackoverflow.com/users/273767/cubbi) I wish there was some way to hail him and get more information about it. – Jonathan Mee Jul 15 '16 at 19:08
  • 1
    Best way to hail a wiki editor is to write something on their user page, and the best way to clarify a wiki page is to write something on the discussion tab of that page. That sentence starts with "informally..." - I was trying to summarize the ODR in simple English because the standardese became way too thick (technically, taking an address is not odr use for unqualified pure virtuals, as noted a bit lower on the same page) – Cubbi Jul 15 '16 at 22:46
  • @KABoissonneault I've asked the obvious followup here: http://stackoverflow.com/q/38437533/2642059 – Jonathan Mee Jul 18 '16 at 13:10

1 Answers1

2

3.2/2:

An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) or a subexpression thereof. ... A non-overloaded function whose name appears as a potentially-evaluated expression or a member of a set of candidate functions, if selected by overload resolution when referred to from a potentially-evaluated expression, is odr-used, unless it is a pure virtual function and its name is not explicitly qualified.

Then 3.2/3:

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 definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is odr-used.

The function name is definitely not an unevaluated operand (for example to sizeof, decltype), AND it appears in an expression, so it's potentially evaluated. Then the second one requires exactly one non-inline definition, or identical inline definitions in each translation unit.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • This is the crux of your logic: "A non-overloaded function whose name appears as a potentially-evaluated expression... is odr-used" But I'm not seeing where taking the address of the function is evaluating it. For example `decltype(foo(int{ 13 }))` is not evaluating `foo`. Is `&foo` evaluating it? I'm not certain from these quotes. – Jonathan Mee Jul 15 '16 at 18:52
  • 2
    @Jonathan Mee The standard *explicitly states* that contexts like as an operand to `decltype` are not potentially evaluated but that in any other context when a name appears in an expression it is potentially-evaluated. – Mark B Jul 15 '16 at 18:59
  • @JonathanMee Think of it this way, how could `bar` possibly work as a function pointer without having instantiated `foo`? Also, this is the same circumstance where you get linker errors with things like `static const int = 4; int j; std::min(i, j)` – Barry Jul 15 '16 at 19:18
  • @MarkB http://en.cppreference.com/w/cpp/language/definition%23One_Definition_Rule which was [cited by KABoissonneault](http://stackoverflow.com/questions/38402133/should-taking-the-address-of-a-templatized-function-trigger-its-compilation#comment64212686_38402133) concur with you: "an object is odr-used if its address is taken" – Jonathan Mee Jul 15 '16 at 19:31
  • @Barry It's weird though. All the compilers I test allow me to take the address of functions which are declared but not defined. How does that work? I guess since I'm doing testing in a one .cpp file setup, declaring them in a .cpp allocates space for them? – Jonathan Mee Jul 15 '16 at 19:33