In my application I use a class to flag elements that are inidicated by positive numbers (see code below). The template parameter of class Stamp
is usually an unsigned integer
. The advantage of flagging with a counter is, that clear()
usually executes fast on huge vectors, as one increment of the counter invalidates all flags. Currently, only in my unit tests, I use boolean
as template argument. Using boolean
comes closest to the naive implementation of flagging numbers. But the increment operator for boolean
is deprecated and will soon vanish from the standard and the compiler complains already about deprecation (not knowing that the part it's complaining about wouldn't even be executed in case of boolean
). How would you specialize method clear()
for the boolean
case? I could not get it right, I tried it by just adding the the following definition.
template<>
void Stamp<bool>::clear() {
std::fill(stamped.begin(), stamped.end(), false);
}
Now the compiler complains about multiple definitions of clear()
. How is template specialization done right in that case. And what other possibilities do I have to fix this class in modern c++?
template <class T> class Stamp {
private:
std::vector<T> stamped;
T stamp;
public:
Stamp(unsigned int size) {
stamped.resize(size, std::numeric_limits<T>::min());
stamp = std::numeric_limits<T>::min();
}
~Stamp() { }
void clear() {
if (stamp < std::numeric_limits<T>::max()) {
stamp++;
}
else {
std::fill(stamped.begin(), stamped.end(), std::numeric_limits<T>::min());
stamp = std::numeric_limits<T>::min() + 1;
}
}
void unset(unsigned int index) {
assert(index < stamped.size());
stamped[index] = std::numeric_limits<T>::min();
}
void set(unsigned int index) {
assert(index < stamped.size());
stamped[index] = stamp;
}
bool isStamped(unsigned int index) const {
return stamped[index] == stamp;
}
};
EDIT: Using the answer of @Constructor I could come up with a method specialization by adding another definition of clear() to the header like this:
template<>
inline void Stamp<bool>::clear() {
std::fill(stamped.begin(), stamped.end(), false);
stamp = true;
}
This is kind of ugly but it actually works. Neither compiler nor tests choke on it.
The full (or explicit) function template specialization is not a template. So you should treat it like a normal function.
There are two possibilities not to violate ODR (One Definition Rule) when you are working with functions or methods of classes:
1) place the declaration of the function/method in a header file and its definition in some cpp file:
// Stamp.h
template<>
void Stamp<bool>::clear();
// Stamp.cpp
template<>
void Stamp<bool>::clear()
{
std::fill(stamped.begin(), stamped.end(), false);
stamp = true;
}
2) mark it as inline
and place its definition in your header file:
// Stamp.h
template<>
inline void Stamp<bool>::clear()
{
std::fill(stamped.begin(), stamped.end(), false);
stamp = true;
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments