在编译时检查函数是否具有外部链接

时间:2019-06-25 00:04:52

标签: c++ templates 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;
}

理由

我真正关心的是传递函数指针作为模板参数是否有效。以下代码在GCC中失败,说明fn没有外部链接。

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;
}

如果我将lambda_ptr换成指向常规函数的constexpr指针,则代码可以正常编译,因为该函数将具有外部链接。

从本质上讲,我希望能够避免在有可能将其编码为模板参数时发送函数指针的运行时开销。但是,我仍然希望能够在不能作为模板参数的情况下发送函数指针。因此,我想构造一个has_external_linkage模板,以便选择合适的路径。

1 个答案:

答案 0 :(得分:0)

恕我直言,使用函数地址作为模板参数是UB,您永远不要使用它。原因是,对于不同平台上的不同编译器,函数地址执行时间可能是未知的。

它可以在具有VM并为本地功能分配静态虚拟地址的体系结构上工作没有任何意义,因为UB允许以任何方式工作,甚至是您期望的工作方式;)

相反,如其他问题所建议的那样,您可以按值传递函数对象。