template <> // the following is a template class with no templated parameters
class Storage8<bool> // we're specializing Storage8 for bool
{
// What follows is just standard class implementation details
private:
unsignedchar m_tType;
public:
void Set(int nIndex, bool tType)
{
// Figure out which bit we're setting/unsetting
// This will put a 1 in the bit we're interested in turning on/off
unsignedchar nMask = 1 << nIndex;
if (tType) // If we're setting a bit
m_tType |= nMask; // Use bitwise-or to turn that bit on
else // if we're turning a bit off
m_tType &= ~nMask; // bitwise-and the inverse mask to turn that bit off
}
bool Get(int nIndex)
{
// Figure out which bit we're getting
unsignedchar nMask = 1 << nIndex;
// bitwise-and to get the value of the bit we're interested in
// Then implicit cast to boolean
return m_tType & nMask;
}
};
This code belongs to Adam. Comments have been written by him.No copyright offense.
The code is out of context; you cannot be expected to understand it.
Specializing templated classes is very similar to specializing templated functions. This example may be more obvious:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
template<typename T> //just your standard template
T CombineTwoThings(T a, T b)
{
return a + b; //works for most things, from numbers to std::string
}
template<> //indicates we are creating a specialization
bool CombineTwoThings<bool>(bool a, bool b) //we replace T with the specialized type and indicate the type in the function name
{
return a || b;
}
//...
CombineTwoThings(1, 2); //calls the first version, returns 3
CombineTwoThings<short>(1, 2); //calls the first version, returns 3
CombineTwoThings(true, false); //calls the second version, returns true
CombineTwoThings<bool>(false, false); //calls the second version, returns false
With classes it is basically the same:
1 2 3 4 5 6 7 8 9 10
template<typename T>
class MyClass
{
//class definition for T
};
template<>
class MyClass<std::string>
{
//class definition for std::string
};
MyClass<int>, MyClass<float>, etc. all refer to the first version, but MyClass<std::string> will use the second version.
Since you haven't provided the declaration for Storage8<>, it's difficult to tell what that template provides or why it's being used since what you've provided appears to be self contained.
What you've provided is a simple class that gets, sets or clears a bit in m_tType.
Do you understand how the two functions work?
@LB thanks for the example..
@AbstractAnon That's what I am not able to understand. I know the basics of
bitwise AND(&) , bitwise OR(|) , bitwise XOR(^) and bitwise NOT(~). But how is that used to set the bits in those get/set functions , I don't understand.
[Note: There can be no partial specialisation of a function of any kind. --end note]
Raman009 wrote:
"But how is that used to set the bits in those get/set functions , I don't understand."
The lines are commented, so what are you not comfortable with?
Raman009 wrote:
"This line confuses me the most:
unsignedchar nMask = 1 << nIndex;"
This is a shift-left operation. It's commonly used to index the bits of a byte. Just like arrays, shifting 1 to the left by 1 will reference the second bit of the byte. For instance:
In addition, shifting to the left is equivalent to multiplication by powers of two, and shifting to the right is equivalent to dividing by powers of two.
Because the last bit of a signed integer (normally the most significant bit) is used to indicate whether or not the value is positive (LOW) or negative (HIGH). The remaining 7 bits are used to represent the actual value [127 maximum]. Because bit-flag values are almost never negative, "unsigned" is used instead for a larger range of possible bit-flag values.
Raman009 wrote:
"int can be used to have the same functionality ie to set the bits on or off OR to determine whether any bit is on or off. Isn't it ?"