Fil*_*ues 2 c++ templates operator-overloading
我正在构建一个BigInt类,当重载运算符时,| 和^,都将具有相似的函数语法,我想知道是否可以模拟运算符本身:
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;
}
Run Code Online (Sandbox Code Playgroud)
其中A [n]返回带有第n个数字(二进制)的bool,并将其应用于运算符&,| 和^,这样我就不会写出3个运算符重载,它们对于2个字母的例外都是相同的.
我知道这种语法不起作用,但我问是否有任何方法可以做你可能期望这种语法做的事情:用&替换K,| 或^,只有你在代码中写(a和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&);
};
Run Code Online (Sandbox Code Playgroud)
一个想法是定义一个在操作符函数上模板化的辅助函数(因为你不能在操作符本身上模板化),然后在相应的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); }
Run Code Online (Sandbox Code Playgroud)
我会写这个:
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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我lhs通过引用并修改它.这是故意的.这对应于&=和|=.
template<class F>
BigInt bitwiseCreate( F&& f, BigInt lhs, BigInt const& rhs ) {
bitwiseReplace( std::forward<F>(f), lhs, rhs );
return lhs;
}
Run Code Online (Sandbox Code Playgroud)
这对应于+或|.
在你的班上:
BigInt& operator=(const BigInt&)=default;
BigInt& operator=(BigInt&&)=default;
BigInt(const BigInt&)=default;
BigInt(BigInt&&)=default;
Run Code Online (Sandbox Code Playgroud)
有默认的移动/复制分配/构造,因为它们在这里做正确的事情.
现在你只需写一行:
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 ); }
Run Code Online (Sandbox Code Playgroud)
这需要少量的胶水代码.
左侧由值表示意味着
auto r = a | b | c;
Run Code Online (Sandbox Code Playgroud)
是有效的 - 结果a | b被移动(实际上被省略)(a|b) | c没有执行复制.
这样做的另一个好处是你可以std::vector<bool>用一个替换你std::vector<uint32_t>.只需编写wordwiseReplace并wordwiseCreate采用一个函数,并uint32_t以非常类似的方式对每个函数进行操作.
你可以用多一点额外的工作,甚至实现+与-这种方式.功能对象可以携带进位信息.您必须检查末端是否有溢出/下溢并进行调整.
*并/需要更多的工作.
| 归档时间: |
|
| 查看次数: |
99 次 |
| 最近记录: |