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

关于标准库模板添加额外默认模板参数的合规性及std::destroy_at实现差异的技术问询

关于标准库模板添加额外默认模板参数的合规性及std::destroy_at实现差异的技术问询

先来看这段让人头疼的代码:

#include <memory>

class A {
protected:
    ~A() = default;
    friend void std::destroy_at<A>(A*); // libstdc++ 编译通过,libc++ 编译失败
public:
    void f() {
        std::destroy_at(this);
    }
};

int main() {
}

这段代码的奇怪之处在于:它在GCC的libstdc中能正常编译,但换到Clang的libc就直接报错了。问题根源出在两个标准库对std::destroy_at的实现差异上:

  • libc++的实现给模板加了一个额外的默认模板参数,用来排除数组类型:
    template<typename T, std::enable_if_t<!std::is_array_v<T>, int> = 0>
    void destroy_at(T*) { ... }
    
  • 而C++标准里对std::destroy_at的定义是没有这个额外参数的简洁版本:
    template<typename T>
    void destroy_at(T*) { ... }
    

那核心问题来了:标准库实现能不能给标准规定的模板添加额外的默认模板参数?这种做法符合C++标准吗?

咱们直接看C++标准的相关规定:标准允许标准库实现为标准模板添加额外的默认模板参数,但有一个硬性要求:这些额外参数不能破坏用户代码的兼容性——也就是说,用户按照标准写法编写的代码,必须能在该实现下正常工作。

回到这个案例:libc给destroy_at加的默认模板参数,导致用户显式指定模板参数的friend声明std::destroy_at<A>(A*)无法匹配到libc的模板(因为libc的模板需要两个模板参数,而用户只指定了一个),这就违反了标准的兼容性要求。所以libc的这个实现其实是不符合标准的,而libstdc++的实现更贴合标准的定义,所以能正常处理用户的代码。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 10:48:02