为什么这样模棱两可?我该怎么做才能解决此问题?

时间:2018-08-12 08:54:01

标签: c++ compiler-errors c++14 bit-fields

这在C ++中的Microsoft Visual Studio 2017中。它说语句bigbits<2> ok2 = (ok >> sq) & 1;不明确。它是如何模棱两可的,我该怎么办?

这是代码。

bigbits.cpp

#include <iostream>
#include "bigbits.h"

int main()
{
    bigbits<2> ok = 0x10101010;
    int sq = 5;
    bigbits<2> ok2 = (ok >> sq) & 1;

    system("PAUSE");

    return 0;
}

bigbits.h

#ifndef BIGBITS_H_
#define BIGBITS_H_

#include <cinttypes>
#include <utility>

constexpr uint32_t lower_dword(uint64_t n) {
    return (uint32_t)(n & UINT32_MAX);
}

constexpr uint32_t upper_dword(uint64_t n) {
    return (uint32_t)(n >> 32);
}

template<uint32_t n> class bigbits;

template<> 
class bigbits<0U> {};

template<> 
class bigbits<1U> {
private:
    uint32_t m_head;

    constexpr void rshft(uint32_t n) {
        m_head >>= n;
    }

    constexpr void lshft(uint32_t n) {
        m_head <<= n;
    }

    constexpr void b_or(const bigbits& other) {
        m_head |= other.m_head;
    }

    constexpr void b_and(const bigbits& other) {
        m_head &= other.m_head;
    }

    constexpr void b_xor(const bigbits& other) {
        m_head ^= other.m_head;
    }

    constexpr void b_not() {
        m_head = ~m_head;
    }

    constexpr uint32_t rshft_(uint32_t n) {
        uint32_t carry = m_head & ((1 << n) - 1);
        m_head >>= n;
        return carry;
    }

    constexpr void lshft_(uint32_t n, uint32_t carry) {
        m_head <<= n;
        m_head |= carry >> (32 - n);
    }

    constexpr void minus_one_() {
        m_head = m_head == 0 ? UINT32_MAX : m_head - 1;
    }

public:
    constexpr bigbits() : m_head(0) {}
    constexpr bigbits(const bigbits& other) : m_head(other.m_head) {}
    constexpr bigbits(uint32_t n) : m_head(n) {}
    constexpr bigbits(int n) : bigbits((uint32_t)n) {}
    constexpr bigbits(uint64_t n) : m_head(lower_dword(n)) {}

    constexpr bigbits& operator=(const bigbits& other) {
        m_head = other.m_head;
        return *this;
    }
    constexpr bigbits& operator=(uint32_t n) {
        m_head = n;
        return *this;
    }
    constexpr bigbits& operator=(int n) {
        return operator=((uint32_t)n);
    }
    constexpr bigbits& operator=(uint64_t n) {
        m_head = lower_dword(n);
        return *this;
    }

    constexpr operator uint32_t() const {
        return m_head;
    }

    constexpr operator int() const {
        return (int)m_head;
    }

    constexpr operator uint64_t() const {
        return (uint64_t)m_head;
    }

    constexpr operator bool() const {
        return (bool)m_head;
    }

    constexpr bool operator==(const bigbits& other) const {
        return m_head == other.m_head;
    }

    constexpr bool operator==(uint32_t n) const {
        return m_head == n;
    }

    constexpr bool operator==(int n) const {
        return operator==((uint32_t)n);
    }

    constexpr bool operator!=(const bigbits& other) const {
        return m_head != other.m_head;
    }

    constexpr bool operator!=(uint32_t n) const {
        return m_head != n;
    }

    constexpr bool operator!=(int n) const {
        return operator!=((uint32_t)n);
    }

    constexpr bool operator<(const bigbits& other) const {
        return m_head < other.m_head;
    }

    constexpr bool operator<(uint32_t n) const {
        return m_head < n;
    }

    constexpr bool operator<(int n) const {
        return operator<((uint32_t)n);
    }

    constexpr bool operator>(const bigbits& other) const {
        return m_head > other.m_head;
    }

    constexpr bool operator>(uint32_t n) const {
        return m_head > n;
    }

    constexpr bool operator>(int n) const {
        return operator>((uint32_t)n);
    }

    constexpr bool operator<=(const bigbits& other) const {
        return m_head <= other.m_head;
    }

    constexpr bool operator<=(uint32_t n) const {
        return m_head <= n;
    }

    constexpr bool operator<=(int n) const {
        return operator<=((uint32_t)n);
    }

    constexpr bool operator>=(const bigbits& other) const {
        return m_head >= other.m_head;
    }

    constexpr bool operator>=(uint32_t n) const {
        return m_head >= n;
    }

    constexpr bool operator>=(int n) const {
        return operator>=((uint32_t)n);
    }

    constexpr bigbits& operator>>=(uint32_t n) {
        rshft(n);
        return *this;
    }

    constexpr bigbits& operator>>=(int n) {
        return *this >>= (uint32_t)n;
    }

    constexpr bigbits& operator<<=(uint32_t n) {
        lshft(n);
        return *this;
    }

    constexpr bigbits& operator<<=(int n) {
        return *this <<= (uint32_t)n;
    }

    constexpr bigbits& operator|=(const bigbits& other) {
        b_or(other);
        return *this;
    }

    constexpr bigbits& operator&=(const bigbits& other) {
        b_and(other);
        return *this;
    }

    constexpr bigbits& operator^=(const bigbits& other) {
        b_xor(other);
        return *this;
    }

    constexpr bigbits operator~() const {
        bigbits ret = *this;
        ret.b_not();
        return ret;
    }

    constexpr bigbits& minus_one() {
        minus_one_();
        return *this;
    }

    friend class bigbits<2>;

};

template<uint32_t n>
class bigbits : protected bigbits<n-1U> {
private:
    uint32_t m_head;

    typedef bigbits<n - 1U> inherited;

    constexpr inherited& tail() { return *this; }
    constexpr const inherited& tail() const { return *this; }

    constexpr void rshft(uint32_t n) {
        while (n > 0) {
            uint32_t t = n > 31 ? 31 : n;
            rshft_(t);
            n -= t;
        }
    }

    constexpr void lshft(uint32_t n) {
        while (n > 0) {
            uint32_t t = n > 31 ? 31 : n;
            lshft_(t, 0);
            n -= t;
        }
    }

    constexpr void b_or(const bigbits& other) {
        m_head |= other.m_head;
        tail().b_or(other.tail());
    }

    constexpr void b_and(const bigbits& other) {
        m_head &= other.m_head;
        tail().b_xor(other.tail());
    }

    constexpr void b_xor(const bigbits& other) {
        m_head ^= other.m_head;
        tail().b_xor(other.tail());
    }

    constexpr void b_not() {
        m_head = ~m_head;
        tail().b_not();
    }

    constexpr uint32_t rshft_(uint32_t n) {
        uint32_t carry = m_head & ((1 << n) - 1);
        m_head >>= n;
        m_head |= tail().rshft_(n) << (32 - n);
        return carry;
    }

    constexpr void lshft_(uint32_t n, uint32_t carry) {
        uint32_t carry2 = m_head & (UINT32_MAX ^ ((1 << (32 - n)) - 1));
        m_head <<= n;
        m_head |= carry >> (32 - n);
        tail().lshft_(n, carry2);
    }

    //returns a reference
    constexpr void minus_one_() {
        if (m_head == 0) {
            m_head = UINT32_MAX;
            tail().minus_one_();
        }
        else {
            m_head -= 1;
        }
    }

public:
    constexpr bigbits() : m_head(0), inherited(0) {}
    constexpr bigbits(const bigbits& other) : m_head(other.m_head), inherited(other.tail()) {}
    constexpr bigbits(uint32_t n) : m_head(n), inherited(0U) {}
    constexpr bigbits(int n) : bigbits((uint32_t)n) {}
    constexpr bigbits(uint64_t n) : m_head(lower_dword(n)), inherited(upper_dword(n)) {}

    constexpr bigbits& operator=(const bigbits& other) {
        m_head = other.m_head;
        tail() = other.tail();
        return *this;
    }
    constexpr bigbits& operator=(uint32_t n) {
        m_head = n;
        tail() = 0U;
        return *this;
    }
    constexpr bigbits& operator=(int n) {
        return operator=((uint32_t)n);
    }
    constexpr bigbits& operator=(uint64_t n) {
        m_head = lower_dword(n);
        tail() = upper_dword(n);
        return *this;
    }

    constexpr operator uint32_t() const {
        return m_head;
    }

    constexpr operator int() const {
        return (int)m_head;
    }

    constexpr operator uint64_t() const {
        return (uint64_t)m_head | ((uint64_t)(uint32_t)tail() << 32);
    }

    constexpr operator bool() const {
        return (bool)m_head || (bool)tail();
    }

    constexpr bool operator==(const bigbits& other) const {
        return (m_head == other.m_head) && (tail() == other.tail());
    }

    constexpr bool operator==(uint32_t n) const {
        return (m_head == n) && (tail() == 0);
    }

    constexpr bool operator==(int n) const {
        return operator==((uint32_t)n);
    }

    constexpr bool operator!=(const bigbits& other) const {
        return (m_head != other.m_head) && (tail() != other.tail());
    }

    constexpr bool operator!=(uint32_t n) const {
        return (m_head != n) && (tail() != 0);
    }

    constexpr bool operator!=(int n) const {
        return operator!=((uint32_t)n);
    }

    constexpr bool operator<(const bigbits& other) const {
        if (tail() < other.tail())
            return true;
        else if (tail() > other.tail())
            return false;
        else
            return m_head < other.m_head;
    }

    constexpr bool operator<(uint32_t n) const {
        if (tail() > 0) return false;
        else return m_head < n;
    }

    constexpr bool operator<(int n) const {
        return operator<((uint32_t)n);
    }

    constexpr bool operator>(const bigbits& other) const {
        if (tail() > other.tail())
            return true;
        else if (tail() < other.tail())
            return false;
        else
            return m_head > other.m_head;
    }

    constexpr bool operator>(uint32_t n) const {
        if (tail() > 0) return true;
        else return m_head < n;
    }

    constexpr bool operator>(int n) const {
        return operator>((uint32_t)n);
    }

    constexpr bool operator<=(const bigbits& other) const {
        if (tail() < other.tail())
            return true;
        else if (tail() > other.tail())
            return false;
        else
            return m_head <= other.m_head;
    }

    constexpr bool operator<=(uint32_t n) const {
        if (tail() != 0) return false;
        else return m_head <= n;
    }

    constexpr bool operator<=(int n) const {
        return operator<=((uint32_t)n);
    }

    constexpr bool operator>=(const bigbits& other) const {
        if (tail() > other.tail())
            return true;
        else if (tail() < other.tail())
            return false;
        else
            return m_head >= other.m_head;
    }

    constexpr bool operator>=(uint32_t n) const {
        if (tail() != 0) return true;
        else return m_head >= n;
    }

    constexpr bool operator>=(int n) const {
        return operator>=((uint32_t)n);
    }

    constexpr bigbits& operator>>=(uint32_t n) {
        rshft(n);
        return *this;
    }

    constexpr bigbits& operator>>=(int n) {
        return *this >>= (uint32_t)n;
    }

    constexpr bigbits& operator<<=(uint32_t n) {
        lshft(n);
        return *this;
    }

    constexpr bigbits& operator<<=(int n) {
        return *this <<= (uint32_t)n;
    }

    constexpr bigbits& operator|=(const bigbits& other) {
        b_or(other);
        return *this;
    }

    constexpr bigbits& operator&=(const bigbits& other) {
        b_and(other);
        return *this;
    }

    constexpr bigbits& operator^=(const bigbits& other) {
        b_xor(other);
        return *this;
    }

    constexpr bigbits operator~() const {
        bigbits ret = *this;
        ret.b_not();
        return ret;
    }

    //returns a reference
    constexpr bigbits& minus_one() {
        minus_one_();
        return *this;
    }

    friend class bigbits<n + 1U>;

};

template<uint32_t a>
constexpr bigbits<a> operator>>(const bigbits<a>& first, uint32_t n) {
    bigbits<a> ret = first;
    return ret >>= n;
}

template<uint32_t a>
constexpr bigbits<a> operator>>(const bigbits<a>& first, int n) {
    bigbits<a> ret = first;
    return ret >>= n;
}

template<uint32_t a>
constexpr bigbits<a> operator<<(const bigbits<a>& first, uint32_t n) {
    bigbits<a> ret = first;
    return ret <<= n;
}

template<uint32_t a>
constexpr bigbits<a> operator<<(const bigbits<a>& first, int n) {
    bigbits<a> ret = first;
    return ret <<= n;
}

template<uint32_t a>
constexpr bigbits<a> operator|(const bigbits<a>& first, const bigbits<a>& second) {
    bigbits<a> ret = first;
    return ret |= second;
}

template<uint32_t a>
constexpr bigbits<a> operator&(const bigbits<a>& first, const bigbits<a>& second) {
    bigbits<a> ret = first;
    return ret &= second;
}

template<uint32_t a>
constexpr bigbits<a> operator^(const bigbits<a>& first, const bigbits<a>& second) {
    bigbits<a> ret = first;
    return ret ^= second;
}

//returns a copy
template<uint32_t a>
constexpr bigbits<a> minus_one(const bigbits<a>& first) {
    bigbits<a> ret = first;
    return ret.minus_one();
}

template<uint32_t a, class Head>
constexpr void assign_bigbits2_(bigbits<a>& b, Head&& h) {
    b |= h;
}

template<uint32_t a, class Head, class...Tail>
constexpr void assign_bigbits2_(bigbits<a>& b, Head&& h, Tail&&...t) {
    b |= h;
    b <<= 32;
    assign_bigbits2_(b, std::forward<Tail>(t)...);
}

template<class...Args>
constexpr bigbits<sizeof...(Args)> assign_bigbits(Args&&...args) {
    bigbits<sizeof...(Args)> ret = 0;
    assign_bigbits2_(ret, std::forward<Args>(args)...);
    return ret;
}

#endif

1 个答案:

答案 0 :(得分:0)

好的,所以我已修复它。我添加了 bigbits :: operator&()的更多重载。问题在于它试图将 bigbits 转换为一种基本类型(例如int或bool)。进一步的测试表明,主要问题在于 bigbits :: operator!=()的逻辑。我现在已经解决了。

该项目的目的是能够将开源国际象棋引擎Senpai 1.0(根据GNU通用公共许可证发行)的位板扩展到更大的棋盘。我现在已经成功地使Senpai在其位板上使用 bigbits 而不是 uint64 。在WinBoard中对其进行测试,就引擎的强度,动作的有效性或运行速度而言,似乎没有任何重大的性能下降。这是因为我使用了C ++ 11模板和C ++ 14版本的 constexpr ,它们将大部分计算移至编译时,从而使运行时的计算最少。由于64位整数比32位整数要花费更长的时间(因为后者是大多数现代系统所固有的),因此额外的 bigbits 计算不会对性能产生重大影响。 >

这是更新的bigbits.h代码。对于Senpai未使用的功能,我不能保证100%的功能是正确的,但是可以在Senpai中使用:

/*
Bigbits Copyright (C) 2018 beneficii.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef BIGBITS_H_
#define BIGBITS_H_

#include <cinttypes>
#include <utility>

constexpr uint32_t lower_dword(uint64_t n) {
    return (uint32_t)(n & UINT32_MAX);
}

constexpr uint32_t upper_dword(uint64_t n) {
    return (uint32_t)(n >> 32);
}

template<uint32_t n> class bigbits;

template<> 
class bigbits<0U> {};

template<> 
class bigbits<1U> {
private:
    uint32_t m_head;

    constexpr void rshft(uint32_t n) {
        m_head >>= n;
    }

    constexpr void lshft(uint32_t n) {
        m_head <<= n;
    }

    constexpr void b_or(const bigbits& other) {
        m_head |= other.m_head;
    }

    constexpr void b_and(const bigbits& other) {
        m_head &= other.m_head;
    }

    constexpr void b_xor(const bigbits& other) {
        m_head ^= other.m_head;
    }

    constexpr void b_not() {
        m_head = ~m_head;
    }

    constexpr uint32_t rshft_(uint32_t n) {
        uint32_t carry = m_head & ((1 << n) - 1);
        m_head >>= n;
        return carry;
    }

    constexpr void lshft_(uint32_t n, uint32_t carry) {
        m_head <<= n;
        m_head |= carry >> (32 - n);
    }

    constexpr void minus_one_() {
        m_head = m_head == 0 ? UINT32_MAX : m_head - 1;
    }

public:
    constexpr bigbits() : m_head(0) {}
    constexpr bigbits(const bigbits& other) : m_head(other.m_head) {}
    constexpr bigbits(uint32_t n) : m_head(n) {}
    constexpr bigbits(int n) : bigbits((uint32_t)n) {}
    constexpr bigbits(uint64_t n) : m_head(lower_dword(n)) {}

    constexpr bigbits& operator=(const bigbits& other) {
        m_head = other.m_head;
        return *this;
    }
    constexpr bigbits& operator=(uint32_t n) {
        m_head = n;
        return *this;
    }
    constexpr bigbits& operator=(int n) {
        return operator=((uint32_t)n);
    }
    constexpr bigbits& operator=(uint64_t n) {
        m_head = lower_dword(n);
        return *this;
    }

    constexpr operator uint32_t() const {
        return m_head;
    }

    constexpr operator int() const {
        return (int)m_head;
    }

    constexpr operator uint64_t() const {
        return (uint64_t)m_head;
    }

    constexpr operator bool() const {
        return (bool)m_head;
    }

    constexpr bool operator==(const bigbits& other) const {
        return m_head == other.m_head;
    }

    constexpr bool operator==(uint32_t n) const {
        return m_head == n;
    }

    constexpr bool operator==(int n) const {
        return operator==((uint32_t)n);
    }

    constexpr bool operator!=(const bigbits& other) const {
        return m_head != other.m_head;
    }

    constexpr bool operator!=(uint32_t n) const {
        return m_head != n;
    }

    constexpr bool operator!=(int n) const {
        return operator!=((uint32_t)n);
    }

    constexpr bool operator<(const bigbits& other) const {
        return m_head < other.m_head;
    }

    constexpr bool operator<(uint32_t n) const {
        return m_head < n;
    }

    constexpr bool operator<(int n) const {
        return operator<((uint32_t)n);
    }

    constexpr bool operator>(const bigbits& other) const {
        return m_head > other.m_head;
    }

    constexpr bool operator>(uint32_t n) const {
        return m_head > n;
    }

    constexpr bool operator>(int n) const {
        return operator>((uint32_t)n);
    }

    constexpr bool operator<=(const bigbits& other) const {
        return m_head <= other.m_head;
    }

    constexpr bool operator<=(uint32_t n) const {
        return m_head <= n;
    }

    constexpr bool operator<=(int n) const {
        return operator<=((uint32_t)n);
    }

    constexpr bool operator>=(const bigbits& other) const {
        return m_head >= other.m_head;
    }

    constexpr bool operator>=(uint32_t n) const {
        return m_head >= n;
    }

    constexpr bool operator>=(int n) const {
        return operator>=((uint32_t)n);
    }

    constexpr bigbits& operator>>=(uint32_t n) {
        rshft(n);
        return *this;
    }

    constexpr bigbits& operator>>=(int n) {
        return *this >>= (uint32_t)n;
    }

    constexpr bigbits& operator<<=(uint32_t n) {
        lshft(n);
        return *this;
    }

    constexpr bigbits& operator<<=(int n) {
        return *this <<= (uint32_t)n;
    }

    constexpr bigbits& operator|=(const bigbits& other) {
        b_or(other);
        return *this;
    }

    constexpr bigbits& operator&=(const bigbits& other) {
        b_and(other);
        return *this;
    }

    constexpr bigbits& operator^=(const bigbits& other) {
        b_xor(other);
        return *this;
    }

    constexpr bigbits operator~() const {
        bigbits ret = *this;
        ret.b_not();
        return ret;
    }

    constexpr bigbits& minus_one() {
        minus_one_();
        return *this;
    }

    friend class bigbits<2>;

};

template<uint32_t n>
class bigbits : protected bigbits<n-1U> {
private:
    uint32_t m_head;

    typedef bigbits<n - 1U> inherited;

    constexpr inherited& tail() { return *this; }
    constexpr const inherited& tail() const { return *this; }

    constexpr void rshft(uint32_t n) {
        while (n > 0) {
            uint32_t t = n > 31 ? 31 : n;
            rshft_(t);
            n -= t;
        }
    }

    constexpr void lshft(uint32_t n) {
        while (n > 0) {
            uint32_t t = n > 31 ? 31 : n;
            lshft_(t, 0);
            n -= t;
        }
    }

    constexpr void b_or(const bigbits& other) {
        m_head |= other.m_head;
        tail().b_or(other.tail());
    }

    constexpr void b_and(const bigbits& other) {
        m_head &= other.m_head;
        tail().b_and(other.tail());
    }

    constexpr void b_xor(const bigbits& other) {
        m_head ^= other.m_head;
        tail().b_xor(other.tail());
    }

    constexpr void b_not() {
        m_head = ~m_head;
        tail().b_not();
    }

    constexpr uint32_t rshft_(uint32_t n) {
        uint32_t carry = m_head & ((1 << n) - 1);
        m_head >>= n;
        m_head |= tail().rshft_(n) << (32 - n);
        return carry;
    }

    constexpr void lshft_(uint32_t n, uint32_t carry) {
        uint32_t carry2 = m_head & (UINT32_MAX ^ ((1 << (32 - n)) - 1));
        m_head <<= n;
        m_head |= carry >> (32 - n);
        tail().lshft_(n, carry2);
    }

    //returns a reference
    constexpr void minus_one_() {
        if (m_head == 0) {
            m_head = UINT32_MAX;
            tail().minus_one_();
        }
        else {
            m_head -= 1;
        }
    }

public:
    constexpr bigbits() : m_head(0), inherited(0) {}
    constexpr bigbits(const bigbits& other) : m_head(other.m_head), inherited(other.tail()) {}
    constexpr bigbits(uint32_t n) : m_head(n), inherited(0U) {}
    constexpr bigbits(int n) : bigbits((uint32_t)n) {}
    constexpr bigbits(uint64_t n) : m_head(lower_dword(n)), inherited(upper_dword(n)) {}

    constexpr bigbits& operator=(const bigbits& other) {
        m_head = other.m_head;
        tail() = other.tail();
        return *this;
    }
    constexpr bigbits& operator=(uint32_t n) {
        m_head = n;
        tail() = 0U;
        return *this;
    }
    constexpr bigbits& operator=(int n) {
        return operator=((uint32_t)n);
    }
    constexpr bigbits& operator=(uint64_t n) {
        m_head = lower_dword(n);
        tail() = upper_dword(n);
        return *this;
    }

    constexpr operator uint32_t() const {
        return m_head;
    }

    constexpr operator int() const {
        return (int)m_head;
    }

    constexpr operator uint64_t() const {
        return (uint64_t)m_head | ((uint64_t)(uint32_t)tail() << 32);
    }

    constexpr operator bool() const {
        return (bool)m_head || (bool)tail();
    }

    constexpr bool operator==(const bigbits& other) const {
        return (m_head == other.m_head) && (tail() == other.tail());
    }

    constexpr bool operator==(uint32_t n) const {
        return (m_head == n) && (tail() == 0);
    }

    constexpr bool operator==(int n) const {
        return operator==((uint32_t)n);
    }

    constexpr bool operator!=(const bigbits& other) const {
        return !operator==(other);
    }

    constexpr bool operator!=(uint32_t n) const {
        return !operator==(n);
    }

    constexpr bool operator!=(int n) const {
        return operator!=((uint32_t)n);
    }

    constexpr bool operator<(const bigbits& other) const {
        if (tail() < other.tail())
            return true;
        else if (tail() > other.tail())
            return false;
        else
            return m_head < other.m_head;
    }

    constexpr bool operator<(uint32_t n) const {
        if (tail() > 0) return false;
        else return m_head < n;
    }

    constexpr bool operator<(int n) const {
        return operator<((uint32_t)n);
    }

    constexpr bool operator>(const bigbits& other) const {
        if (tail() > other.tail())
            return true;
        else if (tail() < other.tail())
            return false;
        else
            return m_head > other.m_head;
    }

    constexpr bool operator>(uint32_t n) const {
        if (tail() > 0) return true;
        else return m_head < n;
    }

    constexpr bool operator>(int n) const {
        return operator>((uint32_t)n);
    }

    constexpr bool operator<=(const bigbits& other) const {
        if (tail() < other.tail())
            return true;
        else if (tail() > other.tail())
            return false;
        else
            return m_head <= other.m_head;
    }

    constexpr bool operator<=(uint32_t n) const {
        if (tail() != 0) return false;
        else return m_head <= n;
    }

    constexpr bool operator<=(int n) const {
        return operator<=((uint32_t)n);
    }

    constexpr bool operator>=(const bigbits& other) const {
        if (tail() > other.tail())
            return true;
        else if (tail() < other.tail())
            return false;
        else
            return m_head >= other.m_head;
    }

    constexpr bool operator>=(uint32_t n) const {
        if (tail() != 0) return true;
        else return m_head >= n;
    }

    constexpr bool operator>=(int n) const {
        return operator>=((uint32_t)n);
    }

    constexpr bigbits& operator>>=(uint32_t n) {
        rshft(n);
        return *this;
    }

    constexpr bigbits& operator>>=(int n) {
        return *this >>= (uint32_t)n;
    }

    constexpr bigbits& operator<<=(uint32_t n) {
        lshft(n);
        return *this;
    }

    constexpr bigbits& operator<<=(int n) {
        return *this <<= (uint32_t)n;
    }

    constexpr bigbits& operator|=(const bigbits& other) {
        b_or(other);
        return *this;
    }

    constexpr bigbits& operator&=(const bigbits& other) {
        b_and(other);
        return *this;
    }

    constexpr bigbits& operator^=(const bigbits& other) {
        b_xor(other);
        return *this;
    }

    constexpr bigbits operator~() const {
        bigbits ret = *this;
        ret.b_not();
        return ret;
    }

    //returns a reference
    constexpr bigbits& minus_one() {
        minus_one_();
        return *this;
    }

    friend class bigbits<n + 1U>;

};

template<uint32_t a>
constexpr bigbits<a> operator>>(const bigbits<a>& first, uint32_t n) {
    bigbits<a> ret = first;
    return ret >>= n;
}

template<uint32_t a>
constexpr bigbits<a> operator>>(const bigbits<a>& first, int n) {
    bigbits<a> ret = first;
    return ret >>= n;
}

template<uint32_t a>
constexpr bigbits<a> operator<<(const bigbits<a>& first, uint32_t n) {
    bigbits<a> ret = first;
    return ret <<= n;
}

template<uint32_t a>
constexpr bigbits<a> operator<<(const bigbits<a>& first, int n) {
    bigbits<a> ret = first;
    return ret <<= n;
}

template<uint32_t a>
constexpr bigbits<a> operator|(const bigbits<a>& first, const bigbits<a>& second) {
    bigbits<a> ret = first;
    return ret |= second;
}

template<uint32_t a>
constexpr bigbits<a> operator|(const bigbits<a>& first, uint32_t n) {
    bigbits<a> ret = first;
    return ret |= n;
}

template<uint32_t a>
constexpr bigbits<a> operator|(const bigbits<a>& first, int n) {
    bigbits<a> ret = first;
    return ret |= n;
}

template<uint32_t a>
constexpr bigbits<a> operator&(const bigbits<a>& first, const bigbits<a>& second) {
    bigbits<a> ret = first;
    return ret &= second;
}

template<uint32_t a>
constexpr bigbits<a> operator&(const bigbits<a>& first, uint32_t n) {
    bigbits<a> ret = first;
    return ret &= n;
}

template<uint32_t a>
constexpr bigbits<a> operator&(const bigbits<a>& first, int n) {
    bigbits<a> ret = first;
    return ret &= n;
}

template<uint32_t a>
constexpr bigbits<a> operator^(const bigbits<a>& first, const bigbits<a>& second) {
    bigbits<a> ret = first;
    return ret ^= second;
}

template<uint32_t a>
constexpr bigbits<a> operator^(const bigbits<a>& first, uint32_t n) {
    bigbits<a> ret = first;
    return ret ^= n;
}

template<uint32_t a>
constexpr bigbits<a> operator^(const bigbits<a>& first, int n) {
    bigbits<a> ret = first;
    return ret ^= n;
}

//returns a copy
template<uint32_t a>
constexpr bigbits<a> minus_one(const bigbits<a>& first) {
    bigbits<a> ret = first;
    return ret.minus_one();
}

template<uint32_t a, class Head>
constexpr void assign_bigbits2_(bigbits<a>& b, Head&& h) {
    b |= h;
}

template<uint32_t a, class Head, class...Tail>
constexpr void assign_bigbits2_(bigbits<a>& b, Head&& h, Tail&&...t) {
    b |= h;
    b <<= 32;
    assign_bigbits2_(b, std::forward<Tail>(t)...);
}

template<class...Args>
constexpr bigbits<sizeof...(Args)> assign_bigbits(Args&&...args) {
    bigbits<sizeof...(Args)> ret = 0;
    assign_bigbits2_(ret, std::forward<Args>(args)...);
    return ret;
}

#endif

要在Senpai 1.0中使用,请包含 bigbits.h ,将 typedef uint64 bit_t; 替换为 typedef bigbits <2> bit_t; ,并在功能 bit :: rest()中将(b-1)替换为 minus_one(b)