C++ - 在保持灵活代码的同时处理 implicit/explicit 转换

C++ - Deal with implicit/explicit casts while keeping flexible code

我正在寻找一种方法来表达 class A 和内置整数类型之间的互操作性,同时在我的代码中保持高度灵活性。例如,我希望能够在 (AA)、(Aint)、(intA) 和 (intint),即我想要 x = y & z 的结果是否 xyz 是类型 class A 或类型 int,只写:

x = y & z;

以下代码有效:

#include <cstdlib>
#include <iostream>

class A {
public:
    int x;

    explicit A(int i) : x(i) {}

    operator int() {
        return this->x;
    }

    A operator &(const A& src) const {
        return A(this->x & src.x);
    }

};

int main() {
    int b(2), b2(0), b3(0);
    A a(3);

    b2 = a & b;
    b3 = b & a;

    std::cout << b2 << std::endl;
    std::cout << b3 << std::endl;

    return 0;
}

但是,如果我在 class A 中添加一个从 Aunsigned int 的新转换函数,这将不再起作用,因为 operator & 定义在 (intint) 以及 (intunsigned int),所以当我这样做时:

b2 = a & b

编译器不知道 a 是否应该转换为 intunsigned int,这是合乎逻辑的。我看到 2 种可能性来解决它:

  1. Aint 之间以及 intA 之间明确实施 operator &。我不希望这样,因为添加与另一种类型的兼容性将需要重新实现需要支持的所有运算符的许多组合。
  2. 强制从内置类型隐式转换为 A,因此只需要 AA 之间的 operator &

对于灵活性和可维护性,我认为解决方案 2 更好。所以我可以实现以下 class A 代替:

class A {
public:
    int x;

    A(int i) : x(i) {}

    A(unsigned int i) : x(i) {}

    explicit operator int() {
        return this->x;
    }

    explicit operator unsigned int() {
        return static_cast<unsigned int>(this->x);
    }

};

A operator &(const A& src1, const A& src2) {
    return A(src1.x & src2.x);
}

现在,虽然转换 from/to int 和 unsigned int 都已定义,但我可以执行是否 (A and A), (A and int), (int and A) and (int and int).

但是我无法编译代码:

b2 = a & b;
b3 = b & a;

因为 b2b3int 和 (a & b) (resp. (b & a)) return a A 和从 Aint 的转换现在必须是显式的,我必须写:

b2 = static_cast<int>(a & b);
b3 = static_cast<int>(b & a);

我的问题(最后)是:

有没有办法编码 class A 这样我就可以做到:

b2 = a & b;
b3 = b & a;

同时只保留 operator & 的一个定义,在(AA)之间?从理论上讲,这可以通过重载 class intoperator =(const A&) 来完成,这在技术上是不可能的。

我认为 bipll 意味着使用 free-standing operator& 函数:

#include <cstdlib>
#include <iostream>

using std::cout;
using std::endl;

class A
{
  int x;
public:
  explicit A(int i) : x{i}
  { }

  explicit A(unsigned i) : x{static_cast<int>(i)}
  { }

  operator int() const
  {
    return this->x;
  }

  operator unsigned() const
  {
    return static_cast<unsigned>(this->x);
  }
};

A operator&(A const& lhs, A const& rhs)
{
  return A(lhs.operator int() & rhs.operator int());
}

A operator&(A const& lhs, int rhs)
{
  return A(lhs.operator int() & rhs);
}

A operator&(int lhs, A const& rhs)
{
  return A(lhs & rhs.operator int());
}

A operator&(A const& lhs, unsigned rhs)
{
  return A(lhs.operator unsigned() & rhs);
}

A operator&(unsigned lhs, A const& rhs)
{
  return A(lhs & rhs.operator unsigned());
}

int main()
{
  auto b = 2;
  auto b2 = 0;
  auto b3 = 0;
  auto u = 2;
  auto u4 = 0u;
  auto u5 = 0u;
  auto a = A{3};

  b2 = a & b;
  b3 = b & a;
  u4 = a & u;
  u5 = u & a;

  cout << b2 << endl;
  cout << b3 << endl;
  cout << u4 << endl;
  cout << u5 << endl;
}

我想我刚刚找到了一个解决方案。请考虑以下代码:

class A {
public:
    int x;

    explicit A(int i) :
            x(i) {
    }

    explicit A(unsigned int i) :
            x(i) {
    }

    operator int() {
        return this->x;
    }

    operator unsigned int() {
        return static_cast<unsigned int>(this->x);
    }

};

template<typename T> A operator &(const A& src1, const T& src2) {
    return A(src1.x & src2);
}

template<typename T> A operator &(const T& src1, const A& src2) {
    return A(src1 & src2.x);
}

int main() {
    int b = 2, b2 = 0, b3 = 0;
    A a(3);

    b2 = a & b;
    b3 = b & a;

    std::cout << b2 << std::endl;
    std::cout << b3 << std::endl;

    return 0;
}

它恰好有效。我看到的唯一问题(虽然这很重要)是您无法控制 operator & 和您没有考虑过的 built-in 类型的影响。

那么新问题: 有没有办法将我的模板 operator & 限制为给定的类型列表(没有模板专门化)?