Check at compile-time if function has external linkage

Viewed 175

Is it possible to check at compile time if a function pointer points to a function with external linkage?

What I'm imagining is a type traits-style template that returns whether or not a function pointer has external linkage.

void linked() {}

void test() {
  // Returns true, since `linked` will have external linkage.
  bool fn = has_external_linkage<linked>::value;

  auto unlinked = []() {};
  constexpr auto *unlinked_ptr = +unlinked;

  // Returns false, since function pointers to lambdas
  // have no external linkage.
  bool lambda = has_external_linkage<unlinked_ptr>::value;
}

Reasoning

What I really care about is whether it's valid to pass a function pointer as a template parameter. The following code fails in GCC, stating that fn does not have external linkage.

template <typename FnType, FnType fn>
void call() {
  fn();
}

int main(int argc, char** argv) {
  auto lambda = []() {};
  constexpr *lambda_ptr = +lambda;
  call<decltype(lambda_ptr), lambda_ptr>();
  return 0;
}

If I swap out lambda_ptr for a constexpr pointer to a regular function, the code compiles fine, since the function will have external linkage.

Essentially, I'd like to be able to avoid the runtime overhead of sending a function pointer whenever it's possible to encode it as a template parameter. However, I'd still like to be able to send the function pointer when it can't be a template parameter. Hence, I'd like to construct something like a has_external_linkage template so I can choose the appropriate path.

1 Answers

IMHO, using function address as template parameter is UB and you should never use that. Reason is, that for different compilers on different platforms function address may be unknown right to execution time.

That it work on architectures which have VM and assign static virtual addresses to local functions didn't mean anything, since UB allowed to work in any way, even one what you expect it to work ;)

Instead, as was proposed in some other question, you can pass function object by value.

Related