【发布时间】:2016-09-27 04:40:25
【问题描述】:
我有一个存储类,它可以添加/删除元素。
它的大多数公共函数共享一个非常相似的签名,如下所示:-
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 函数的解决方案仍然可以接受。
【问题讨论】:
-
unique_ptr 应该添加什么?假设所有权?如果是这样,为什么不创建一个 add(T&&) 函数呢?
-
@rubenvb 是的,假设所有权。创建一个函数
add(T&&)是可以的,但是我认为它并不能解决规则执行的问题。 -
首先,问问自己:为什么要制定这些规则?然后,看看它是否可以正常工作。然后,检查
std::vector的实现,看看它是如何处理这些事情的。如果这不能解决问题,请使用std::is_same添加一些static_asserts 以强制执行带有明确错误消息的规则。不过,这些转换可能已经由编译器强制执行。 -
@rubenvb (1) 当我检查
std::vector时,我发现限制stackoverflow.com/questions/15125631/… 因此,我认为std::vector不是一个很好的例子。 .... (2) 关于static_assert,我的天赋不够。 “Ami Tavory”试图做到这一点(下面的答案),但没有完成,因为它很麻烦。 ... (3)关于“已经强制执行”,如果我自己也能控制的话,我会更高兴。我不喜欢关于模板的不可读的编译器错误。 -
通过原始指针删除 unique_ptr 意味着可能还有其他指向已删除对象的原始指针,这与您对该对象所有权的任何保证相矛盾。这是灾难的秘诀。我强烈建议你重新考虑你在做什么。
标签: c++ templates c++11 unique-ptr template-specialization