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

如何将C++函数/Lambda作为非类型参数传入typedef/using模板?

FILE* f1 = fopen(xxx);
FILE* f2 = fopen(yyy);
smartFp sf1(f1); // 无需传递deleter函数
smartFp sf2(f2);
...

是否可以实现这种`sp_with_deleter`类型?

# 解决方案
当然可以实现,但需要调整模板参数的写法——`std::shared_ptr`的第二个模板参数是**deleter的类型**,而非函数本身。下面提供几种实用的实现方式:

## 方式一:C++17+ 通用模板别名(auto非类型模板参数)
利用C++17支持的`auto`非类型模板参数,结合`std::integral_constant`将函数包装成符合要求的deleter类型:
```cpp
#include <memory>
#include <cstdio>
#include <type_traits>

template<typename T, auto Deleter>
using sp_with_deleter = std::shared_ptr<T, std::integral_constant<decltype(Deleter), Deleter>>;

// 客户端使用
using smartFp = sp_with_deleter<FILE*, fclose>;

// 构造时无需手动传递deleter
FILE* f1 = fopen("test.txt", "r");
smartFp sf1(f1);

std::integral_constant会把传入的函数指针包装成一个可调用对象,std::shared_ptr会自动调用它的operator()来释放资源。

方式二:封装模板类(兼容C++11及以上)

如果需要兼容更早的C++标准,或者想要添加自定义逻辑,可以封装一个模板类继承std::shared_ptr:

#include <memory>
#include <cstdio>

template<typename T, void (*Deleter)(T)>
class SmartPtrWithDeleter : public std::shared_ptr<T> {
public:
    explicit SmartPtrWithDeleter(T ptr) 
        : std::shared_ptr<T>(ptr, Deleter) {}
    
    // 按需继承或添加其他构造函数、成员函数
};

// 客户端使用
using smartFp = SmartPtrWithDeleter<FILE*, fclose>;

FILE* f1 = fopen("test.txt", "r");
smartFp sf1(f1); // 无需传deleter

这种方式可以灵活扩展,比如添加空指针检查、自定义日志等逻辑。

方式三:专属资源封装(最易维护)

如果某个资源的使用频率很高,直接封装专属的智能指针类型是最优选择:

#include <memory>
#include <cstdio>

struct FileDeleter {
    void operator()(FILE* fp) const {
        if (fp) {
            fclose(fp);
            // 后续可以在这里添加日志、错误处理等扩展逻辑
        }
    }
};

using SmartFilePtr = std::shared_ptr<FILE, FileDeleter>;

// 客户端使用
FILE* f1 = fopen("test.txt", "r");
SmartFilePtr sf1(f1);

后续如果需要修改deleter逻辑,只需要修改FileDeleter的operator()即可,所有使用SmartFilePtr的代码都无需改动,完美契合你避免大量修改的需求。

总结
  • 通用场景下,C++17+推荐用auto模板参数结合std::integral_constant实现sp_with_deleter;
  • 需要兼容旧标准或扩展逻辑时,封装模板类是更好的选择;
  • 针对特定资源,专属智能指针的封装方式最简洁、易维护。

内容的提问来源于stack exchange,提问作者gongliming7

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:33:34