是否应该通过Koenig查找找到具有枚举参数的类中的朋友操作符?

时间:2014-01-26 01:29:58

标签: c++ c++11 operator-overloading

请考虑以下代码:

enum A : unsigned { a = 1, b = 2, c = 4 };

class B
{
  friend constexpr A operator|(A a1, A a2)
  { return A(unsigned(a1) | unsigned(a2)); }
};

template <A a>
class C
{
};

int main()
{
  C<a|c> c;
}

使用g ++(4.8.1,-std = c ++ 1)编译时,出现以下错误:

test.C: In function ‘int main()’:
test.C:16:12: error: invalid conversion from ‘unsigned int’ to ‘A’ [-fpermissive]
       C<a|c> c;

这告诉我没有找到运营商。但是,如果代码更改为:

enum A : unsigned { a = 1, b = 2, c = 4 };

constexpr A operator|(A a1, A a2)
{ return A(unsigned(a1) | unsigned(a2)); }

template <A a>
class C
{
};

int main()
{
  C<a|c> c;
}

然后它编译并运行正常。第一种情况下的错误是编译器错误,还是我误解了什么?我想使用Boost.Operators的方法通过从定义运算符的模板声明一个带有基类的类来轻松定义运算符,但是在这种情况下,这个结果排除了。

感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

解决它的另一种方法(除了jogojapan已经提到过),只是在范围之外声明友元函数。

enum A : unsigned { a = 1, b = 2, c = 4 };

//declaration
constexpr A operator|(A a1, A a2);


class B
{
  //definition inside, ok.
  friend constexpr A operator|(A a1, A a2)
  { return A(unsigned(a1) | unsigned(a2)); }
};

template <A a>
class C
{
};

int main()
{
  C<a|c> c;
}

答案 1 :(得分:0)

好的,我采取了另一种方法,这里的代码解决了我的问题:

template <typename UNSIGNED>
struct BitwiseEnum
{
  enum class Enum : UNSIGNED
  {
  };

  constexpr static Enum value(unsigned bit)
  {
    return Enum(UNSIGNED(1) << bit);
  }

  friend constexpr Enum operator|(Enum a, Enum b)
  {
    return Enum(UNSIGNED(a)|UNSIGNED(b));
  }

  friend constexpr Enum operator&(Enum a, Enum b)
  {
    return Enum(UNSIGNED(a)&UNSIGNED(b));
  }

  friend constexpr Enum operator~(Enum a)
  {
    return Enum(~UNSIGNED(a));
  }
};

class MyMask : public BitwiseEnum<unsigned long>
{
};

typedef MyMask::Enum Mask;

constexpr static Mask a = MyMask::value(0);
constexpr static Mask b = MyMask::value(1);
constexpr static Mask c = MyMask::value(2);
constexpr static Mask d = MyMask::value(3);


template <Mask A>
class B
{
};

int main()
{
  B<a|b> test;
}

现在,当我定义了许多像“MyMask”这样的枚举时,它可以相当简单地完成,没有比简单定义的枚举更多的代码。并且它的行为就像人们从位字段枚举中“期望”一样,可以用于强类型检查模板参数等。