【问题标题】:C++ invalid operands to binary expression二进制表达式的 C++ 无效操作数
【发布时间】:2016-02-11 09:38:38
【问题描述】:

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

我有一个定义枚举类的模板类:

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) 这样调用这个函数。

为了在该枚举上使用 &amp;| 运算符而不必每次都手动转换为 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&lt;double&gt;::stat) 获得了正确的类型,但它无法推断出模板...

此外:

  • 显式调用运算符有效 (operator&amp;&lt;Type&gt;(stats, stat::AVERAGE);)
  • 我以为问题出在返回类型上,但调用 stat a = stats &amp; stat::AVERAGE; 不起作用(与之前的错误相同)。

有什么想法吗?

【问题讨论】:

  • @chris 看起来有点不同。在编译错误消息中,编译器似乎知道应该推导的类型(双):'eip::stats&lt;double&gt;::stat' and 'eip::stats&lt;double&gt;::stat'。但是,它仍然无法推导出模板。
  • 编译器知道你正在传递stats&lt;double&gt;::stat 的参数,但这还不足以推断出Type。如果你有template&lt;&gt; class stats&lt;int&gt; {public: using stat = stats&lt;double&gt;::stat;}; 怎么办?这可能存在于其他地方,编译器尚无法知道。然后通过stats&lt;double&gt;::stat 可以有效地将Type 推断为int
  • 好的,所以错误来自基类模板。所以也许解决这个问题的一种方法是在类之外声明枚举?
  • 您可以,或者您可以按照链接中的建议使用Type 而不是stat_t&lt;Type&gt;。你永远不会使用Type,除非作为stat_t 的参数。

标签: c++ c++11 enums compilation bitwise-operators


【解决方案1】:

您的代码有两处错误。

  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&amp;:使其成为类本身的友元运算符:

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

    if (stats & stat::AVERAGE)
    

    不会编译。为此,您可能希望让您的operator&amp; 返回一个intbool,或者使用this answer 的想法,添加一个operator! 并使用它两次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多