简体   繁体   中英

C++11 Template function to “implicity” convert bitset<N> to “unsigned long”

I can create a C++11 Template function to explicitly convert a bitset into an unsigned long:

template<size_t N>
unsigned long U(bitset<N> x) {
    return x.to_ulong();
}

// Explicit conversion
unsigned long y = U(bitset<4>("1010"));

Is there a way to "implicitly" convert bitset to an unsigned long using a C++11 template helper function. For Example, if I assign a bitset to an unsigned long, then I want it to automatically convert the bitset to the correct type:

// What Template Function in C++11?

// Implicit Conversion
unsigned long z = bitset<4>("1010");

(If its not possible to create an implicit convertion rule to convert to "unsigned long using a C++11 template function, its also acceptable to derive a new class from bitset that has casting function to unsigned long. Is that possible as well?)

To implicitly convert A to B , either:

  • B must have a non-explicit constructor taking A , or
  • A must have a non-explicit conversion operator B() .

Both of these must be member functions only.

Since you cannot modify std::bitset or unsigned long the answer is: no, you cannot implicitly convert std::bitset to unsigned long . Only explicitly .

You could wrap std::bitset in your own implicitly convertible class:

template<size_t N>
class MyBitset
{
public:
    // constructors elided here

    operator unsigned long()
    {
        return _bitset.to_ulong();
    }

    operator std::bitset<N>()
    {
        return _bitset; // Note that you get a copy here.
    }

private:
    std::bitset<N> _bitset;
};

Demo

If you are trying to derive from non-polymorphic classes in namespace std (ie those without virtual destructors), you are not writing idiomatic C++ , don't do it. Whether the above is really a solution to your problem we can't tell. If all you need is unsigned long constants from your bitstrings, you could skip the class wrapper and replace its constructors with templated functions directly:

template<size_t N, class CharT>
unsigned long toUlong(const CharT* str,
                 typename std::basic_string<CharT>::size_type n =
                     std::basic_string<CharT>::npos,
                 CharT zero = CharT('0'),
                 CharT one = CharT('1'))
{
    return std::bitset<N>(str, n, zero, one).to_ulong();
}

Demo

Another Solution based on Maxim's Bullet 2:

template<size_t N>
class bits : public bitset<N> {
public:
    bits(unsigned long num) : bitset<N>(num) {}
    bits(char* binstr) : bitset<N>(binstr){}

    operator unsigned long() {
        return this->to_ulong();
    }

    // Slice Bit Range
    unsigned long slice(unsigned L, unsigned R)
    {
        unsigned long P1;
        unsigned long P2;

        if (L>R) {
            P2 = L;
            P1 = R;
        }
        else {
            P2 = R;
            P1 = L;
        }

        unsigned long x = this->to_ulong();
        unsigned long W = P2 - P1 + 1;

        unsigned long Value = (x >> P1) & ((1<<W) - 1);

        return Value;
    }

    // Return Hex String
    string hstr() {
        stringstream xx;
        xx << "0x" << hex << this->to_ulong();
        return xx.str();
    }
};

int main(int argc, char** argv) {
    // Implicit conversion...
    unsigned long xxx = bits<4>("0101");
    unsigned long yyy = bits<4>(xxx).slice(1, 2);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM