C++ - 处理隐式/显式强制转换,同时保持灵活的代码

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

本文关键字:代码 转换 处理 C++      更新时间:2023-10-16

我正在寻找一种方法来表达类A和内置整数类型之间的互操作性,同时在我的代码中保持高度的灵活性。例如,我希望能够在(AA)、(Aint)、(intA)和(intint)之间自由使用operator &,即我想得到x = y & z的结果,xyzclass 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的 cast 函数,这不再起作用,因为operator &是在 (intint之间定义的) 和 (intunsigned int),所以当我这样做时:

b2 = a & b

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

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

对于灵活性和可维护性,我认为解决方案 2 要好得多。所以我可以改为实现以下类 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);
}

现在,虽然从/到 int 和无符号 int 的转换都是定义的,但我可以执行 (AA)、(Aint)、(intA) 和 (intint)。

但是我无法编译代码:

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

因为b2b3int和(a&b)(或(b&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之间)?理论上,这可以通过类int的重载operator =(const A&)来完成,这在技术上是不可能的。

我认为bipll意味着使用独立的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 &的效果。

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