为什么我需要重新声明方法/成员以进行部分模板专业化?

时间:2016-09-28 22:34:19

标签: c++ templates specialization

我对C ++模板相对较新,并试图找出部分模板专业化。我正在使用模板实现几个相关的数据结构:用于概率存在/不存在查询的布隆过滤器(基于位数组),以及用于丰富查询的计数布隆过滤器(具有整数数组)。我从以下类定义开始。

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;
};

addget的通用实现都是正确的,但get可以针对基于位阵列的Bloom过滤器进行优化。如果我只是尝试添加带签名的方法......

template<typename ElementType>
bool filter<ElementType, bool, 1>::get(ElementType element);

...我从编译器收到以下错误消息。

error: nested name specifier 'filter<ElementType, bool, 1>::'
    for declaration does not refer into a class, class template
    or class template partial specialization

通过一些阅读,我了解到除非整个类部分专业化,否则单个方法不能部分专业化。这实际上很方便,因为这让我有机会为(部分)专业课提供新标签。我把它添加到我的标题的底部......

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> {};

...并从...

更改了方法签名
template<typename ElementType>
bool filter<ElementType, bool, 1>::get(ElementType element);

...到...

template<typename ElementType>
bool bloomfilter<ElementType>::get(ElementType element);

显然这还不够。我需要在部分专用的类定义中明确定义bloomfilter::get方法。

template<typename ElementType>
class bloomfilter : public filter<ElementType, bool, 1>
{
    public:
        bool get(ElementType element);
};

但是现在编译器抱怨_arrays是未声明的标识符。直到我添加它才能正确编译。

template<typename ElementType>
class bloomfilter : public filter<ElementType, bool, 1>
{
    public:
        bool get(ElementType element);

    protected:
        std::vector<std::vector<bool>> _arrays;
};

为什么我必须在部分专业化的模板类中明确定义get_arrays?为什么他们不从泛型类继承?

2 个答案:

答案 0 :(得分:4)

非常确定您的问题是您需要使用_arrays来限定名称this。尝试将_arrays的所有实例更改为this->_arrays

在C ++中,为了访问模板基类的成员,你必须进一步限定名称,以澄清名称是否依赖于基类的模板参数(我认为)。如果您对此功能的更多技术细节感兴趣(比我更好地解释),请查看here

答案 1 :(得分:0)

<强>注释

您可以考虑标记调度:

#include <iostream>
#include <vector>
using size_t = std::size_t;

template<typename ElementType, typename CounterType, size_t maxcount>
class filter
{
    private:
    template <typename C, size_t>
    struct Tag {};

    using bloom_filter_tag = Tag<bool, 1>;

    template <typename Tag>
    CounterType get_dispatch(Tag, ElementType element) {
        std::cout << "generic\n";
        return CounterType{};
    }

    CounterType get_dispatch(bloom_filter_tag, ElementType element) {
        std::cout << "bloom filter\n";
        return CounterType{};
    }


    public:
    CounterType get(ElementType element) {
        return get_dispatch(Tag<CounterType, maxcount>(), element);
    }
};


int main() {
    filter<int, bool, 1> bloom;
    bloom.get(1);
    filter<int, double, 2> generic;
    generic.get(1);
}

但是,define cindy const实际上正在回答您的问题。