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

Sim*_*non 0 c++ enums compilation bitwise-operators c++11

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

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

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

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

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

 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();
 }
Run Code Online (Sandbox Code Playgroud)

我们可以在这里调用这个函数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));
}
Run Code Online (Sandbox Code Playgroud)

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

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) {
^
Run Code Online (Sandbox Code Playgroud)

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

此外:

  • 明确调用运算符works(operator&<Type>(stats, stat::AVERAGE);)
  • 我认为问题来自返回类型,但调用stat a = stats & stat::AVERAGE;不起作用(与之前相同的错误).

任何的想法?

Bar*_*rry 5

您的代码有两个问题.

  1. 这是一个不可导出的背景:

    template <typename Type>
    stat_t<Type>
    operator&(const stat_t<Type>& lhs, const stat_t<Type>& rhs) { ... }
    
    Run Code Online (Sandbox Code Playgroud)

    这个想法和你写的一样:

    template <typename T>
    void foo(typename cls<T>::type ) { ... }
    
    Run Code Online (Sandbox Code Playgroud)

    T除非你告诉它,否则编译器无法弄清楚可能存在的东西.因此,您必须operator&在我们实际上不需要进行演绎的地方定义您:在类本身中将其设置为友元运算符:

    friend stat operator&(const stat& lhs, const stat& rhs) { ... }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 一旦我们解决了这个问题,我们就会遇到另一个问题,即a stat不能在上下文中转换成bool这样的表达式:

    if (stats & stat::AVERAGE)
    
    Run Code Online (Sandbox Code Playgroud)

    不会编译.为此,你可能希望让你的operator&回报intbool,或者使用这个答案的想法,添加operator!并使用它两次.