C++模板<Operator>

C++ Template<Operator>

本文关键字:Operator gt lt 模板 C++      更新时间:2023-10-16

我目前正在建立一个bigint类,并且在超载运算符时&amp; |和 ^,所有这些都具有相似的函数语法,我想知道是否可以像这样模拟操作员自己:

template<operator K> 
BigInt operator K( const BigInt& a, const BigInt& b )
{
 BigInt Result = 0;
 uint64_t Max = max(a.GetSize() , b.GetSize()) /* max(a,b) is defined outside */
 for (uint64_t n=0; n < Max; n++)
 {
  Result[n] = a[n] K b[N];
 }
 return Result;
}

[n]以(二进制(的n数字返回bool,然后将其应用于操作员&amp;,|^,这样我就不会写3个操作员过载,这些过载与2个字母相同。

我知道这种语法不起作用,但是我问是否有任何方法可以做您可能期望的语法要做的事情:by&amp;,|或 ^,并且仅在代码中编写(a&amp; b(时。

如果在这里有所帮助是我对课堂的定义:

class BigInt
{
private:
    vector<bool> num;
public:
    /* Constructors */
    BigInt();
    template<class T> BigInt(T);
    /* Class Methods */
    void RLZ(); /* Remove Leading Zeroes */
    uint64_t GetSize() const;
    void print();
    /* Operator Overloads */
    std::vector<bool>::reference operator[] (uint64_t);
    bool operator[] (uint64_t) const;
    BigInt& operator=(const BigInt&);
};

一个想法是定义在操作员函数上模板上的助手函数(因为您无法在操作员本身上模板(,然后实例化模板在适当的Bigint运营商的定义中。例如:

template <class OperatorFn> 
BigInt bitwiseOperator(const BigInt& a, const BigInt& b) const
{
    BigInt Result = 0;
    uint64_t Max = max(a.GetSize(), b.GetSize());
    for (uint64_t n=0; n < Max; n++)
    {
        Result[n] = OperatorFn{}(a[n], b[N]);
    }
    return Result;
}
BigInt operator&(const BigInt& a, const BigInt& b) const { return bitwiseOperator<std::bit_and<bool>>(a, b); }
BigInt operator|(const BigInt& a, const BigInt& b) const { return bitwiseOperator<std::bit_or<bool>>(a, b); }
BigInt operator^(const BigInt& a, const BigInt& b) const { return bitwiseOperator<std::bit_xor<bool>>(a, b); }

我会写这篇:

template<class F>
BigInt& bitwiseReplace( F&& f, BigInt& lhs, BigInt const& rhs ) {
  auto max = (std::max)(lhs.GetSize(), rhs.GetSize());
  for (uint64_t i=0; i < max; ++i)
    lhs[i] = f( lhs[i], rhs[i] );
  return lhs;
}

请注意,我通过参考将lhs进行修改。这是故意的。这对应于&=|=

template<class F>
BigInt bitwiseCreate( F&& f, BigInt lhs, BigInt const& rhs ) {
  bitwiseReplace( std::forward<F>(f), lhs, rhs );
  return lhs;
}

这对应于+|

在您的班级中:

BigInt& operator=(const BigInt&)=default;
BigInt& operator=(BigInt&&)=default;
BigInt(const BigInt&)=default;
BigInt(BigInt&&)=default;

在这里做正确的事情,有默认的移动/复制分配/构造。

现在您只需要写一行:

BigInt& operator&=( BigInt const& rhs ) { return bitwiseReplace( std::bit_and<bool>{}, *this, rhs ); }
BigInt& operator|=( BigInt const& rhs ) { return bitwiseReplace( std::bit_or<bool>{}, *this, rhs ); }
friend BigInt operator&( BigInt lhs, BigInt const& rhs ) { return bitwiseCreate( std::bit_and<bool>{}, std::move(lhs), rhs ); }
friend BigInt operator|( BigInt lhs, BigInt const& rhs ) { return bitwiseCreate( std::bit_or<bool>{}, std::move(lhs), rhs ); }

这需要少量的胶水代码。

用价值占据的左侧意味着

auto r = a | b | c;

是有效的 - a | b的结果被移动(实际上是浮动(,没有执行任何副本。

另一个优点是您可以用std::vector<uint32_t>替换std::vector<bool>。只需编写wordwiseReplacewordwiseCreate,它以非常相似的方式在每个uint32_t上运行并在每个CC_12上运行。

您可以使用一些其他工作,甚至可以以这种方式实现+-。该功能对象可以携带随身携带信息。您必须检查末端是否有溢流/下底并进行调整。

*/将需要更多的工作。