在 class<std::unique_ptr<B>> 中强制模板函数为 T=B*
Enforce template function to be T=B* inside a class<std::unique_ptr<B>>
我有一个存储class,它可以add/remove元素。
它的大多数 public 函数共享一个非常相似的签名,如图所示函数:-
template<class T> class Storage{
public: void add(T& t){ ... }
//... other fields,functions
}
很棒的是 T
可以是值或原始指针。
现在我想升级此存储以也支持 T=std::unique_ptr
。
这就是我想要完成的:-
Storage<std::unique_ptr<B>> store;
B* b = new B();
store.add(b); //my attempt - it is currently not supported
这是我支持新功能的草稿:-
template<class T> class Storage{
public: template<class TWeak> void add(TWeak& tw){ ... }
//... other fields,functions
}
从草案来看,我认为使用 TWeak
作为模板参数有些危险 - TWeak
可以是任何东西。
粗略地说,TWeak
只能是T's weakpointer
,这与我的意图相矛盾。
更具体地说,我想强制执行此规则:-
When T=std::unique_ptr<B> ==> TWeak have to be B* or std::unique_ptr<B>
When T=B* ==> TWeak have to be B*
When T=B ==> TWeak have to be B
如何优雅地执行规则?
具有 2 个 add
函数的解决方案仍然可以接受。
More specifically, I want to enforce this rule :-
When T=std::unique_ptr<B>
==> TWeak
have to be B*
or std::unique_ptr
When T=B*
==> TWeak
have to be B*
When T=B
==> TWeak
have to be B
您可以编写具有专业化的“执行者”class,如下所示:
#include <type_traits>
#include <memory>
template<typename T, typename B, typename Tweak>
class tweak_enforcer
{
static_assert(std::is_same<Tweak, B>::value, "must be of same type");
};
template<typename B, typename Tweak>
class tweak_enforcer<std::unique_ptr<B>, B, Tweak>
{
static_assert(std::is_same<Tweak, B*>::value || std::is_same<Tweak, std::unique_ptr<B>>::value, "must be of pointer type");
};
每个专业都使用 static_assert
to check one or more expected type matches via std::is_same
。
然后你可以像这样使用它(取消注释任何注释行会导致构建失败并显示适当的消息):
int main() {
{ tweak_enforcer<int, int, int> dummy; }
// { tweak_enforcer<int *, int *, int> dummy; }
{ tweak_enforcer<int *, int *, int *> dummy; }
{ tweak_enforcer<std::unique_ptr<int>, int, int *> dummy; }
{ tweak_enforcer<std::unique_ptr<int>, int, std::unique_ptr<int>> dummy; }
// { tweak_enforcer<std::unique_ptr<int>, int, std::shared_ptr<int>> dummy; }
}
为了保持界面简单,您可以使用特化来扩展 Storage
,它服务于封闭类型,例如 unique_ptr
:
template<class T>
class Storage<std::unique_ptr<T>> : public Storage<T*>{
public: using Storage<T*>::add;
public: void add(std::unique_ptr<T>& t){ ... } //
};
我们继承,Storage<T*>
因为:
根据您的要求,T*
与 unique_ptr<T>
配合得很好
问题
- 包括所有常用方法。
add()
等特殊方法
分别定义并且 using
指令用于取消隐藏
基本方法
用法:
Storage<int> si; si.add(/*int variable*/);
Storage<int*> spi; spi.add(/*int* variable*/);
Storage<std::unique_ptr<int>> su; su.add(/*int* or unique_ptr<int> variable*/);
这里是demo.
我有一个存储class,它可以add/remove元素。
它的大多数 public 函数共享一个非常相似的签名,如图所示函数:-
template<class T> class Storage{
public: void add(T& t){ ... }
//... other fields,functions
}
很棒的是 T
可以是值或原始指针。
现在我想升级此存储以也支持 T=std::unique_ptr
。
这就是我想要完成的:-
Storage<std::unique_ptr<B>> store;
B* b = new B();
store.add(b); //my attempt - it is currently not supported
这是我支持新功能的草稿:-
template<class T> class Storage{
public: template<class TWeak> void add(TWeak& tw){ ... }
//... other fields,functions
}
从草案来看,我认为使用 TWeak
作为模板参数有些危险 - TWeak
可以是任何东西。
粗略地说,TWeak
只能是T's weakpointer
,这与我的意图相矛盾。
更具体地说,我想强制执行此规则:-
When T=std::unique_ptr<B> ==> TWeak have to be B* or std::unique_ptr<B>
When T=B* ==> TWeak have to be B*
When T=B ==> TWeak have to be B
如何优雅地执行规则?
具有 2 个 add
函数的解决方案仍然可以接受。
More specifically, I want to enforce this rule :-
When
T=std::unique_ptr<B>
==>TWeak
have to beB*
or std::unique_ptrWhen
T=B*
==>TWeak
have to beB*
When
T=B
==>TWeak
have to beB
您可以编写具有专业化的“执行者”class,如下所示:
#include <type_traits>
#include <memory>
template<typename T, typename B, typename Tweak>
class tweak_enforcer
{
static_assert(std::is_same<Tweak, B>::value, "must be of same type");
};
template<typename B, typename Tweak>
class tweak_enforcer<std::unique_ptr<B>, B, Tweak>
{
static_assert(std::is_same<Tweak, B*>::value || std::is_same<Tweak, std::unique_ptr<B>>::value, "must be of pointer type");
};
每个专业都使用 static_assert
to check one or more expected type matches via std::is_same
。
然后你可以像这样使用它(取消注释任何注释行会导致构建失败并显示适当的消息):
int main() {
{ tweak_enforcer<int, int, int> dummy; }
// { tweak_enforcer<int *, int *, int> dummy; }
{ tweak_enforcer<int *, int *, int *> dummy; }
{ tweak_enforcer<std::unique_ptr<int>, int, int *> dummy; }
{ tweak_enforcer<std::unique_ptr<int>, int, std::unique_ptr<int>> dummy; }
// { tweak_enforcer<std::unique_ptr<int>, int, std::shared_ptr<int>> dummy; }
}
为了保持界面简单,您可以使用特化来扩展 Storage
,它服务于封闭类型,例如 unique_ptr
:
template<class T>
class Storage<std::unique_ptr<T>> : public Storage<T*>{
public: using Storage<T*>::add;
public: void add(std::unique_ptr<T>& t){ ... } //
};
我们继承,Storage<T*>
因为:
-
根据您的要求,
T*
与unique_ptr<T>
配合得很好 问题- 包括所有常用方法。
add()
等特殊方法 分别定义并且using
指令用于取消隐藏 基本方法
用法:
Storage<int> si; si.add(/*int variable*/);
Storage<int*> spi; spi.add(/*int* variable*/);
Storage<std::unique_ptr<int>> su; su.add(/*int* or unique_ptr<int> variable*/);
这里是demo.