C ++模板<operator>

时间:2018-02-16 18:12:48

标签: c++ templates operator-overloading

我正在构建一个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;
}

其中A [n]返回带有第n位(二进制)的bool,并将其应用于运算符&amp;,|和^,这样我就不会写出3个操作符重载,除了2个字母外,它们是相同的。

我知道这种语法不起作用,但我问是否有任何方法可以做到你希望这种语法做的事情:用&amp ;,替换K,|或^,只有你在代码中写(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&);
};

2 个答案:

答案 0 :(得分:7)

一个想法是定义一个在运算符函数上模板化的辅助函数(因为你不能在运算符本身上模板化),然后在适当的定义中实例化你的模板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); }

答案 1 :(得分:5)

我会这样写:

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的结果被移动(实际上被省略)到(a|b) | c而没有执行副本。

这样做的另一个好处是,您可以将std::vector<bool>替换为std::vector<uint32_t>。只需编写wordwiseReplacewordwiseCreate即可获取函数,并以非常类似的方式对每个uint32_t进行操作。

您可以通过一些额外的工作,甚至以这种方式实施+-。功能对象可以携带进位信息。你必须检查最后是否有溢出/下溢并进行调整。

*/需要更多工作。