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

C++ 在编译时检查函数是否有外部链接,c++,templates,linkage,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 a

是否可以在编译时检查函数指针是否指向具有外部链接的函数

我想象的是一个类型特性样式模板,它返回函数指针是否具有外部链接

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;
}
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
替换为指向常规函数的
constepr
指针,则代码编译良好,因为函数将具有外部链接

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

本质上,我希望能够避免在可能将函数指针编码为模板参数时发送函数指针的运行时开销。但是,我仍然希望能够在函数指针不能作为模板参数时发送它。因此,我想构造一个类似“代码>具有外部链接”的模板,这样我就可以选择合适的路径。

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

它在具有虚拟机的架构上工作,并将静态虚拟地址分配给本地函数,这并不意味着什么,因为UB允许以任何方式工作,即使是您期望它工作的方式;)


相反,正如在另一个问题中所提出的,您可以通过值传递函数对象。

使用模板来确定某个内容是否作为模板参数有效,这有点像循环,不是吗?在C++11中,外部链接的要求被放宽了。您必须将其用于这些其他功能—C++17,甚至用于
constexpr
一元
+
。你是说“任何联系”吗?即使在C++20中这也很轻松……您不需要走这么远。函数指针正常。如果您真的关心,请使用函数对象使其可以内联。@DavisHerring您是对的,我并不真正关心它是否具有
external
链接,只关心它是否可以用作模板参数。我使用的是C++17,所以任何有效的都可以。未定义的行为与您的意见无关。链接器在运行时参与分配函数地址(最多包括)。(符号可见性可以通过为一个函数提供多个地址来解决这一问题,但这是一个与基本接口设计分开管理的问题。)使用函数地址作为模板参数是否实际上是未定义的行为?如果有人能指出我在C++标准中对这个问题的引用,我会感兴趣。@ XII1408:当然,不是。为什么语言会有一个特性,尽管在编译时非常明显,但始终是未定义的行为?在当前C++中,有许多允许的模板参数类型,但禁止列表被列出,尽管有一个关于使用函数指针的问题。