如何在模板化类中专门化模板化方法?

时间:2015-09-17 06:35:48

标签: c++ templates template-specialization

我发现C ++模板难以理解。现在我试图专门化一个模板化类的模板化成员函数:

template <bool COW>
class BaseReferencedObject {
public:
    BaseReferencedObject()                                 : refCount(0) {}
    BaseReferencedObject(const BaseReferencedObject<COW>&) : refCount(0) {}
    BaseReferencedObject<COW>& operator=(const BaseReferencedObject<COW>&) {return *this;}
    template <bool COW2> void increaseRefCount() const;
    void decreaseRefCount() const {refCount--;}
    int getRefCount() const {return refCount;}
private:
    mutable int refCount;
};

class BaseReferencedObject<false>;
class BaseReferencedObject<true >;

template<> void BaseReferencedObject<false>::increaseRefCount<false>() const {refCount++;}
template<> void BaseReferencedObject<true >::increaseRefCount<true >() const {refCount++;}

typedef BaseReferencedObject<false> ReferencedObject;
typedef BaseReferencedObject<true > SharedData      ;

但是,当我尝试编译此代码时,我得到了

SharedPtr.hh:31:62: error: expected initializer before ‘<’ token
 template<> void BaseReferencedObject<false>::increaseRefCount<false>() const {refCount++;}
                                                              ^

这意味着什么,我应该如何继续这样做?我试图通过谷歌搜索找到解决方案,但我还没有找到任何可行的方法。< / p>

顺便说一下,有人可以推荐任何好的资源来更好地理解C ++模板在其核心的工作方式吗?

简要介绍我在这里尝试做什么:我还有一个第二类template <bool COW> class BaseSharedPointer,它是一类共享指针,引用从ReferencedObject或{SharedData继承的对象1}}。我们的想法是,只有使用copy-on-write(COW)的共享指针应该能够引用应该在写入时复制的对象(真正的真组合),并且只能使用不需要的共享指针。使用COW应该能够引用不应该在写入时复制的对象(假 - 错误组合)。不应该允许其他两种组合(true-false,false-true),因为混合使用COW的智能指针和不被认为是不好主意的智能指针。因此,我试图通过仅为允许的组合实例化increaseRefCount方法的特化来使这些组合变得不可能,并且为其他两个特化保留未实例化以引发编译错误,如果某些代码尝试使用它们中的任何一个。

1 个答案:

答案 0 :(得分:3)

您需要添加另一个template<>来专门化成员函数

template<> template<> void BaseReferencedObject<false>::increaseRefCount<false>() const {refCount++;}
template<> template<> void BaseReferencedObject<true >::increaseRefCount<true >() const {refCount++;}

请注意,您只能专门化成员函数以进行周围类模板的特化。

但是,您的代码示例还有两个不完全正确的方面。首先,最好为increaseRefCount提供默认实现(这可以在类模板定义中完成)。第二,你的两行

class BaseReferencedObject<false>;
class BaseReferencedObject<true >;

导致您在评论中提到的有些神秘的编译器错误。如果你use clang instead of g++作为编译器,那么这些行会得到更明确的错误:

  

错误:模板专业化需要&#39;模板&lt;&gt;&#39;

以及错误

  

错误:类型不完整&#39; BaseReferencedObject&#39;以嵌套名称说明符

命名

用于成员函数专业化。原因是您没有定义类模板特化,而只是向前声明它们。但是,它没有必要,因为您可以在不提供完整的类模板特化的情况下专门化成员函数。

这是一个完整的代码示例:

#include <iostream>

template <bool COW>
class BaseReferencedObject {
public:
    BaseReferencedObject()                                 : refCount(0) {}
    BaseReferencedObject(const BaseReferencedObject<COW>&) : refCount(0) {}
    BaseReferencedObject<COW>& operator=(const BaseReferencedObject<COW>&) {return *this;}
    template <bool COW2> void increaseRefCount() const { std::cout << "DEFAULT\n"; refCount++; }
    void decreaseRefCount() const {refCount--;}
    int getRefCount() const {return refCount;}
private:
    mutable int refCount;
};

template<> template<> void BaseReferencedObject<false>::increaseRefCount<false>() const { std::cout << "FALSE\n"; refCount++;}
template<> template<> void BaseReferencedObject<true >::increaseRefCount<true >() const { std::cout << "TRUE \n"; refCount++;}

typedef BaseReferencedObject<false> ReferencedObject;
typedef BaseReferencedObject<true > SharedData      ;

int main()
{
    BaseReferencedObject<false> b0;
    BaseReferencedObject<true > b1;

    b0.increaseRefCount<false>();
    b0.increaseRefCount<true>();
    b1.increaseRefCount<true >();
    b1.increaseRefCount<false>();
}

Live Example

更新:如果您不想要默认实施,则可以明确删除其他组合

template<> template<> void BaseReferencedObject<false>::increaseRefCount<true>() const = delete;
template<> template<> void BaseReferencedObject<true >::increaseRefCount<false >() const = delete;

当您只省略默认实现时,这会产生编译器错误而不是链接器错误。