为何void(*deleter)(T)可作为模板参数?写法兼容性疑问
问题与解答
代码示例
#include <iostream> template <typename T, void(*deleter)(T)> struct MyMoveOnlyHandleType { void reset() { deleter(handle); } T handle; ~MyMoveOnlyHandleType() { reset(); } }; int main() { { MyMoveOnlyHandleType<int, [](int arg) { std::cout << "Hello"; } > my_handle; } }
疑问解答
1. void(*deleter)(T)作为模板参数的合法性
template <typename T, void(*deleter)(T)>是完全合法的非类型模板参数写法。非类型模板参数的核心语法是参数类型 参数名,这里void(*)(T)是函数指针类型,deleter是参数名——这是C语言延续下来的函数指针声明语法,把参数名deleter放在类型的括号中间,本质和template <int N>里的int是类型、N是参数名完全一致,并非错误写法。
2. template <void (*)(int) deleter>的编译差异
你提到的template <void (*)(int) deleter>属于旧式的非类型模板参数语法,早期C++标准允许这种写法,但后续标准更推荐类型 参数名的清晰格式(也就是你代码里的void(*deleter)(T)写法)。不同编译器对旧语法的兼容程度不同:Clang和GCC保留了对这种旧语法的支持,而MSVC对该旧式语法的支持不完善,导致无法编译,这种情况是正常的编译器兼容差异。
3. 补充:C++17的lambda特性
你的代码能在C17后三大编译器编译通过,还因为C17允许无捕获的lambda表达式作为非类型模板参数传递,这是标准新增的特性。
内容的提问来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

