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

为何仅一个重载有效时,operator&仍存在编译歧义?

为什么删除其他类型转换后,HashType64的operator&仍存在歧义?

相关代码

#include <stdint.h>

struct HashType64
{
    inline HashType64(uint64_t h) noexcept : _h(h) {}
    inline operator uint64_t() const noexcept { return _h; }
    inline operator int64_t() const = delete;
    inline operator int32_t() const = delete;
    inline operator uint32_t() const = delete;

private:
    uint64_t _h;
};

uint64_t f() {
    return HashType64(0) & 0xFFULL;
}

编译错误信息

<source>: In function 'uint64_t f()':
<source>:17:26: error: ambiguous overload for 'operator&' (operand types are 'HashType64' and 'long long unsigned int')
   17 |     return HashType64(0) & 0xFFULL;
      |            ~~~~~~~~~~~~~ ^ ~~~~~~~
      |            |               |
      |            HashType64      long long unsigned int
<source>:17:26: note: candidate: 'operator&(uint32_t {aka unsigned int}, long long unsigned int)' (built-in)
   17 |     return HashType64(0) & 0xFFULL;
      |            ~~~~~~~~~~~~~~^~~~~~~~~
<source>:17:26: note: candidate: 'operator&(int32_t {aka int}, long long unsigned int)' (built-in)
<source>:17:26: note: candidate: 'operator&(int64_t {aka long int}, long long unsigned int)' (built-in)
<source>:17:26: note: candidate: 'operator&(uint64_t {aka long unsigned int}, long long unsigned int)' (built-in)

疑问

我理解错误含义,但不明白其产生原因:HashType64仅可转换为uint64_t,其他整数类型转换已被删除,为何operator&仍存在歧义?


解答

核心原因是被删除的转换函数依然会参与重载决议,且它们和保留的转换函数优先级相同,导致编译器无法确定最优转换路径。

C++中,用= delete标记的转换函数并不会从重载候选列表中移除,编译器依然会将其视为可行的转换选项——只有当最终决议选中了被删除的函数时,才会报“使用了删除的函数”错误。

回到你的代码:当计算HashType64(0) & 0xFFULL时,编译器要为左侧的HashType64对象寻找合适的转换,以匹配内置的operator&重载。此时:

  • 保留的operator uint64_t()是一个用户定义转换
  • 被删除的operator int64_t()、operator int32_t()、operator uint32_t()同样属于用户定义转换

这些转换的优先级完全相同,编译器无法判断应该选择哪一个转换来匹配右侧的unsigned long long操作数,因此抛出“重载歧义”错误。

解决方法

有两种常见的解决思路:

  1. 显式转换:在使用时手动将HashType64转换为uint64_t,消除歧义:
    uint64_t f() {
        return static_cast<uint64_t>(HashType64(0)) & 0xFFULL;
    }
    
  2. 重载operator&:为HashType64显式定义与整数类型的按位与运算符,跳过隐式转换的重载决议:
    struct HashType64
    {
        // ... 原有代码 ...
        friend uint64_t operator&(const HashType64& lhs, uint64_t rhs) noexcept {
            return static_cast<uint64_t>(lhs) & rhs;
        }
    };
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 03:41:15