有什么方法可以定义"doubling"运算符吗?

Any way to define a "doubling" operator?

本文关键字:doubling 运算符 定义 什么 方法      更新时间:2023-10-16

我有一个类,它表示一个只能取整数值或半整数值的量,因此它的值在内部存储为值的两倍整数。也就是说:值0.5存储为1,1存储为2,1.5存储为3,等等。让我们用存储的值int TwoA_将其称为class A

这将强制A值正确地为整数或半整数。由于我经常需要使用它们作为它们的真值,所以我自然地生成了一个转换为double的运算符,它只返回0.5 * TwoA_

然而,我经常需要使用两倍的值。我认为对2 * a(aA类型的对象(进行编码以直接返回存储在a中的值TwoA_会很好。

理想情况下,我想做一个运算符,它只在从左边乘以2时才这样做。所有其他情况都将由隐式演员阵容覆盖。

在c++中有什么方法可以做到这一点吗?我想到了某种模板化的乘法运算符。

定义的简单解决方案

friend double operator*(int lhs, const A& rhs)
{ return (lhs == 2) ? rhs.TwoA_ : lhs * static_cast<double>(rhs); }

不是我想要的。2 * a保证是int(但一般来说an_int * a不是(,我想返回一个int

这是一个好奇的问题;如果你只想评论"你为什么要这么做?"(或其变体(,请保持沉默。

编辑:我指的是左边的整数文字2(不是一个测试值是否为2的整数变量(

理解您的问题是,如果您可以重载*运算符,使其根据其中一个参数的值返回不同的数据类型,简短的答案是:否。

长话短说:没有,但也许是的。

double operator*(const int lhs, const A& rhs);

如果lhs是否为2,则该操作员必须在COMPILE TIME上知道,而这一点无法保证。这意味着必须在运行时决定如何处理lhs是否为2的情况。但是运算符返回的数据类型必须在编译时已知。。。

double operator*(const some_type_1& lhs, const A& rhs);
int operator*(const some_type_2& lhs, const A& rhs);

这将获得两种不同的返回类型,但只有在编译时了解这些参数类型的情况下。

template<int T>
struct special_number{};
//...
template<>
int operator*(const special_number<2>&, const A& rhs){
  return rhs.TwoA_;
}
template<int T>
double operator*(const special_number<T>&, const A& rhs){
  return (static_cast<double>(rhs) / 2.0) * T;
}
//usage
int answer1 = special_number<2> * my_a_object;
double answer2 = special_number<3> * my_a_object;

这样就可以了。

struct two_t {
  constexpr two_t() {};
  template<class T>
  constexpr operator T()const{return 2;}
};
constexpr two_t two;

现在:

friend double operator*(two_t lhs, const A& rhs)
{ return rhs.TwoA_; }
friend double operator*(const A& lhs, two_t lhs)
{ return lhs.TwoA_; }

是关于你能做的最好的。

表达式的类型不依赖于值,除非在特殊情况下,常数0可以转换为指针,并且可能导致不同的重载分辨率。

当作为参数传递给*时,不能利用这种特殊情况使2变得特殊。

现在

constexpr std::ptrdiff_t from_digits(std::integer_sequence<char>) {
  return 0;
}
constexpr std::ptrdiff_t compile_time_pow( std::ptrdiff_t base, std::size_t exp ) {
  return exp ? base * compile_time_pow( base, exp-1 ) : std::ptrdiff_t(1);
}
template<char c0, char...cs>
constexpr std::ptrdiff_t from_digits(std::integer_sequence<char, c0, cs...>) {
  return
    compile_time_pow(10, sizeof...(cs))*(c0-'0')
    + from_digits( std::integer_sequence<char, cs...>{} );
}
template<char...cs>
constexpr auto operator"" _integer() {
  return std::integral_constant<std::ptrdiff_t, from_digits( std::integer_sequence<char, cs...>{} )>{};
}

现在,2_integer是值为2的compile_time std::ptrdiff_t,其值以其类型编码。

因此,2_integer * a可以被重写以返回与3_integer * a2 * a不同的类型。