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

VC++ 2022中noexcept运算符相关编译问题咨询

VC++ 2022中noexcept运算符的编译疑问及解答

测试代码

// noexcept测试基类
class MyNoExcept
{
public:
    void Func() noexcept
    {}

    void Func1()
    {}
};

// noexcept测试派生类
class MyNoExcept2 : public MyNoExcept
{
public:
    void Func2() noexcept(noexcept(MyNoExcept::Func()))
    {
        static_assert(noexcept(MyNoExcept::Func()), "MyNoExcept::Func()必须是noexcept");
    }
    // Func1的noexcept声明写法错误!
    void Func3() noexcept(noexcept(static_cast<MyNoExcept*>(this)->Func1)) 
    {
        static_assert(noexcept(static_cast<MyNoExcept*>(this)->Func1), "MyNoExcept::Func1()必须是noexcept");
    }
};

// 测试函数
void TestNoexcept()
{
    MyNoExcept2 m;
    m.Func2();

    // 编译错误 C2056: 非法表达式
    if constexpr (noexcept(MyNoExcept::Func()))
    {
        printf("MyNoExcept::Func()是noexcept\n");
    }

    m.Func3();
}

疑问

    1. 显然noexcept(MyNoExcept::Func())是编译期表达式,为何constexpr if语句无法编译?
    1. Func3中对无参函数MyNoExcept::Func1的noexcept声明及static_assert使用了错误写法,但代码仍能编译并给人安全的假象。预期是if constexpr (noexcept(MyNoExcept::Func()))可正常编译,且void Func3() noexcept(noexcept(static_cast<MyNoExcept*>(this)->Func1))会触发编译错误。

解答

问题1:constexpr if中noexcept表达式编译失败

VC++ 2022对非模板上下文的if constexpr有特殊限制:它要求条件表达式不仅是常量表达式,还要满足“在当前上下文可被编译器明确判定为常量操作”。虽然MyNoExcept::Func()是空实现且标记为noexcept,但VC++在非模板函数的if constexpr中,没有正确识别该函数调用属于常量表达式允许的操作。

两种可行的解决方式:

  • 将TestNoexcept改为模板函数,让表达式处于依赖模板参数的上下文,此时编译器会正确处理:
    template<typename T>
    void TestNoexcept()
    {
        MyNoExcept2 m;
        m.Func2();
    
        if constexpr (noexcept(MyNoExcept::Func()))
        {
            printf("MyNoExcept::Func()是noexcept\n");
        }
    
        m.Func3();
    }
    
  • 直接判断函数类型的noexcept属性,省略函数调用括号,这种写法更简洁且能绕过VC++的限制:
    if constexpr (noexcept(MyNoExcept::Func))
    {
        printf("MyNoExcept::Func()是noexcept\n");
    }
    

问题2:错误写法未触发编译错误

你在Func3中写的static_cast<MyNoExcept*>(this)->Func1是取成员函数的指针,而非调用函数。noexcept(...)在这里判断的是“获取函数指针”这个操作是否会抛出异常——而取成员函数指针的操作本身永远是noexcept的,所以noexcept(...)的结果恒为true,导致static_assert不会触发,函数的noexcept声明也错误地标记为noexcept。

正确写法必须加上函数调用的括号,让noexcept判断的是函数调用的异常属性:

void Func3() noexcept(noexcept(static_cast<MyNoExcept*>(this)->Func1())) 
{
    static_assert(noexcept(static_cast<MyNoExcept*>(this)->Func1()), "MyNoExcept::Func1()必须是noexcept");
}

此时编译器会正确识别Func1()没有noexcept修饰,触发static_assert的编译错误,函数的noexcept声明也会匹配Func1()的实际异常属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 05:40:41