I'm relatively new to C++ templating and trying to figure out partial template specialization. I'm implementing several related data structures using templates: a Bloom filter (based on bit arrays) for probabilistic presence/absence queries, and a counting Bloom filter (with integers arrays) for abundance queries. I'm starting from the following class definition.
template<typename ElementType, typename CounterType, size_t maxcount>
class filter
{
public:
explicit filter(std::vector<size_t> array_sizes);
void add(ElementType element);
CounterType get(ElementType element);
protected:
std::vector<std::vector<CounterType>> _arrays;
};
The generic implementation of both add
and get
is correct, but get
could be optimized for the bit array based Bloom filter. If I just try to add a method with the signature...
template<typename ElementType>
bool filter<ElementType, bool, 1>::get(ElementType element);
...I get the following error message from the compiler.
error: nested name specifier 'filter<ElementType, bool, 1>::'
for declaration does not refer into a class, class template
or class template partial specialization
With a bit of reading, I learned that individual methods cannot be partially specialized unless the entire class is partially specialized. That's actually convenient anyway, as that gives me a chance to provide new labels for the (partially) specialized classes. I added this to the bottom of my header...
template<typename ElementType> class bloomfilter : public filter<ElementType, bool, 1> {};
template<typename ElementType> class countfilter : public filter<ElementType, uint8_t, 255> {};
template<typename ElementType> class bigcountfilter : public filter<ElementType, uint32_t, 8589934591> {};
...and changed the method signature from...
template<typename ElementType>
bool filter<ElementType, bool, 1>::get(ElementType element);
...to...
template<typename ElementType>
bool bloomfilter<ElementType>::get(ElementType element);
Apparently this isn't enough. I need to explicitly define the bloomfilter::get
method in the partially specialized class definition.
template<typename ElementType>
class bloomfilter : public filter<ElementType, bool, 1>
{
public:
bool get(ElementType element);
};
But now the compiler is complaining that _arrays
is an undeclared identifier. It's not until I add this that it compiles correctly.
template<typename ElementType>
class bloomfilter : public filter<ElementType, bool, 1>
{
public:
bool get(ElementType element);
protected:
std::vector<std::vector<bool>> _arrays;
};
Why do I have to explicitly define get
and _arrays
in the partially specialized template class? Why aren't they inherited from the generic class?