C++标准是否定义了结构中成员函数的函数内定义是否必须具有静态链接?

Does the C++ standard define if in-function definitions of member functions in structs must have static linkage?

本文关键字:定义 是否 函数 静态 链接 结构 成员 C++ 标准      更新时间:2023-10-16

我在函数中定义的结构中定义了一个静态函数。我想获取指向内部函数的模板函数指针。

请考虑以下示例:

template <class Func, Func GetToken>
struct token_user {
void foo () { GetToken(); } // Do something with token.
};
struct generator_out {
constexpr static const auto get_token() {return 0;}
};
int main() {
struct generator_in {
constexpr static const auto get_token() {return 0;}
};
// Works fine
token_user<decltype(&generator_out::get_token), &generator_out::get_token>(); 
// Fails with GCC, works with clang and msvc
token_user<decltype(&generator_in::get_token), &generator_in::get_token>();
}

我用我的本地 MSVC 2017 编译器以及 wandbox.org 上的 clang 6.0 和 gcc 8.1 编译器对此进行了测试。MSVC和clang工作,gcc不工作。

谁是正确的?是 clang 和 msvc 太宽容了,扭曲了 c++ 标准,还是 gcc 根本没有实现这一点?(或者它甚至可能是一个错误?标准对此有何规定?

编辑: 来自 gcc 的错误消息:

prog.cc: In function 'int main()':
prog.cc:15:76: error: 'main()::generator_in::get_token' is not a valid template argument for type 'const int (*)()' because 'static constexpr const auto main()::generator_in::get_token()' has no linkage
token_user<decltype(&generator_in::get_token), &generator_in::get_token>(); // Fails with GCC, works with clang and msvc

GCC 是正确的,generator_in::get_token没有链接,不能在声明它的范围之外使用,因此不能用作实例化token_user的参数。

请参阅 [basic.link]/8 和/9(我只包括相关部分(:

。除非另有说明,否则在块范围内声明的名称没有链接。

例:

void f() {
struct A { int x; };  // no linkage
}

这很重要,因为成员函数具有类的链接。 [basic.link]/5:

。成员函数、静态数据成员、类范围的命名类或枚举,或在类范围 Typedef 声明中定义的未命名类或枚举,使得类或枚举具有用于链接目的的 typedef 名称 ([dcl.typedef](,与它所属的类的名称具有相同的链接(如果有(。

所以generator_ingenerator_in::get_token都没有联系。

最后: [basic.link]/2.3:

— 当名称没有链接时,它所表示的实体不能由其他范围的名称引用。