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

为何含constexpr-if与std::is_copy_assignable的C++代码无法编译?

为什么这段带constexpr-if的代码无法编译?

这段代码中,static_assert已经验证Foo不可拷贝赋值,但constexpr-if块内的代码并未被编译器丢弃,从而引发了调用已删除函数的错误。

代码示例

#include <type_traits>

struct Foo {
    Foo() = default;
    Foo const& operator=(Foo const&) = delete;
};

int main()
{
    static_assert(!std::is_copy_assignable_v<Foo>);

    Foo x;
    Foo other;
    if constexpr (std::is_copy_assignable_v<Foo>) {
        other = x;
    }
    return 0;
}

编译错误信息

<source>: In function 'int main()':
<source>:16:17: error: use of deleted function 'const Foo& Foo::operator=(const Foo&)'
   16 |         other = x;
      |                 ^
<source>:5:16: note: declared here
    5 |     Foo const& operator=(Foo const&) = delete;
      |                ^~~~~~
Compiler returned: 1

问题原因与解决方法

问题核心在于非模板上下文下constexpr-if的行为特性:

  • 在非模板函数(比如这里的main)中,即使constexpr-if的条件是常量表达式false,编译器仍会对分支内的代码进行语义检查,而非完全丢弃。
  • 虽然std::is_copy_assignable_v<Foo>确实为false(Foo的拷贝赋值运算符被显式删除,导致other = x表达式非法),但非模板上下文里的false分支代码依然会被编译器检查语义,调用已删除函数自然触发错误。

解决方法是将逻辑迁移到模板函数中:模板上下文里,当constexpr-if的条件是不依赖模板参数的常量false时,分支内的代码会被完全丢弃,不会进行语义检查。示例代码如下:

#include <type_traits>

struct Foo {
    Foo() = default;
    Foo const& operator=(Foo const&) = delete;
};

template<typename T>
void assign_if_possible(T& dest, const T& src) {
    if constexpr (std::is_copy_assignable_v<T>) {
        dest = src;
    }
}

int main()
{
    static_assert(!std::is_copy_assignable_v<Foo>);

    Foo x;
    Foo other;
    assign_if_possible(other, x);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:53:20