我发现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
方法的特化来使这些组合变得不可能,并且为其他两个特化保留未实例化以引发编译错误,如果某些代码尝试使用它们中的任何一个。
答案 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>();
}
更新:如果您不想要默认实施,则可以明确删除其他组合
template<> template<> void BaseReferencedObject<false>::increaseRefCount<true>() const = delete;
template<> template<> void BaseReferencedObject<true >::increaseRefCount<false >() const = delete;
当您只省略默认实现时,这会产生编译器错误而不是链接器错误。