c++ - C++ 标准是否定义了结构中成员函数的函数内定义是否必须具有静态链接?
问题描述
我在函数中定义的结构中定义了一个静态函数。我想获得一个指向内部函数的模板函数指针。
考虑以下示例:
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_in
并generator_in::get_token
没有联系。
最后:[basic.link]/2.3:
— 当名称没有链接时,它所表示的实体不能被其他范围的名称引用。
推荐阅读
- keras - 是否可以在 Keras 中训练层的权重但不能训练其偏差(反之亦然)?
- java - Firebase:我在使用 Google 登录时遇到了麻烦
- node.js - 将迁移更改列续集为 FK,然后撤消失败
- python - RPi 3B+ OpenCV Python3 错误
- python-3.x - 从 Python 3/boto3 使用 QuickSight API 创建具有多个数据集的模板
- tensorflow - 我在 anaconda 提示符下成功安装了 tensorflow,但无法在 jupyter notebook 中导入
- reactjs - 在反应js中加载d3地图
- regex - 用随机字符串向后看 - 解决方法?
- webrtc-android - Android webrtc SIGSEGV 错误
- javascript - 从以编程方式注入的 Chrome 扩展程序中的弹出窗口链接到选项页面