You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 19:36:01