C++ 二进制表达式的无效操作数

C++ invalid operands to binary expression

我在 C++11 中遇到奇怪的编译错误。

我有一个模板化的 class 定义了一个枚举 class:

template <typename Type>
class stats {
public:
  // ...
  enum class stat {
    AVERAGE = (1 << 0),
    STANDARD_DERIVATION = (1 << 1),
    // ...
  };
  // ...
};

我目前想在按位运算中使用这个枚举。

例如,这是该枚举的用法示例:

 template <typename Type>
 void
 stats<Type>::build(stat stats) {
     if (stats & stat::AVERAGE)
         this->build_average();

     if (stats & stat::STANDARD_DEVIATION)
         this->build_standard_deviation();

     if (stats & stat::PERCENTILES)
         this->build_percentiles();

     if (stats & stat::LIMITS)
         this->build_limits();
 }

在哪里我们可以像这样调用这个函数stats.build(stat::AVERAGE | stat::LIMITS)

为了在该枚举上使用 &| 运算符而不必每次都手动转换为 int,我定义了运算符:

template<typename T>
using stat_t = typename eip::stats<T>::stat;

template <typename Type>
stat_t<Type>
operator|(const stat_t<Type>& lhs, const stat_t<Type>& rhs) {
  return static_cast<stat_t<Type>>(static_cast<int>(lhs) | static_cast<int>(rhs));
}

template <typename Type>
stat_t<Type>
operator&(const stat_t<Type>& lhs, const stat_t<Type>& rhs) {
    return static_cast<stat_t<Type>>(static_cast<int>(lhs) & static_cast<int>(rhs));
}

但是,如果我尝试编译,我会收到以下错误:

error: invalid operands to binary expression ('eip::stats<double>::stat' and 'eip::stats<double>::stat')
if (stats & stat::PERCENTILES)
    ~~~~~ ^ ~~~~~~~~~~~~~~~~~
candidate template ignored: couldn't infer template argument 'Type'
operator&(const stat_t<Type>& lhs, const stat_t<Type>& rhs) {
^

我不明白为什么我的过载被忽略了。编译器似乎为 lhs 和 rhs (eip::stats<double>::stat) 获得了正确的类型,但它无法推断模板...

此外:

有什么想法吗?

您的代码有两处错误。

  1. 这是一个不可推导的上下文:

    template <typename Type>
    stat_t<Type>
    operator&(const stat_t<Type>& lhs, const stat_t<Type>& rhs) { ... }
    

    思路和你写的一样:

    template <typename T>
    void foo(typename cls<T>::type ) { ... }
    

    编译器无法弄清楚 T 可能在那里,除非你也告诉它。所以你必须在我们实际上不需要进行推导的地方定义你的 operator& :让它成为 class 本身的友元运算符:

    friend stat operator&(const stat& lhs, const stat& rhs) { ... }
    
  2. 一旦我们解决了这个问题,我们就会遇到另一个问题,即 stat 不能根据上下文转换为 bool 所以这个表达式:

    if (stats & stat::AVERAGE)
    

    无法编译。为此,您可能希望让您的 operator& return 成为 intbool,或者使用 this answer 的想法,添加一个 operator!并使用它两次。