Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在类中强制模板函数为T=B*<;标准::唯一性\u ptr<;B>&燃气轮机;_C++_Templates_C++11_Unique Ptr_Template Specialization - Fatal编程技术网

C++ 在类中强制模板函数为T=B*<;标准::唯一性\u ptr<;B>&燃气轮机;

C++ 在类中强制模板函数为T=B*<;标准::唯一性\u ptr<;B>&燃气轮机;,c++,templates,c++11,unique-ptr,template-specialization,C++,Templates,C++11,Unique Ptr,Template Specialization,我有一个存储类,它可以添加/删除元素 其大多数公共功能共享一个非常相似的签名,如功能所示:- template<class T> class Storage{ public: void add(T& t){ ... } //... other fields,functions } 以下是我的草稿,以支持新功能:- template<class T> class Storage{ public: template<class TWea

我有一个存储类,它可以添加/删除元素

其大多数公共功能共享一个非常相似的签名,如功能所示:-

template<class T> class Storage{
    public: void add(T& t){ ... }
    //... other fields,functions
}
以下是我的草稿,以支持新功能:-

template<class T> class Storage{
    public: template<class TWeak> void add(TWeak& tw){  ...   }
    //... other fields,functions
}
如何优雅地执行规则?
仍然可以接受具有2个添加功能的解决方案

更具体地说,我想强制执行此规则:-

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
T=std::unique\u ptr
==>
TWeak
必须是
B*
或std::unique\u ptr

T=B*
==>
TWeak
必须是
B*

T=B
==>
TWeak
必须是
B

您可以编写一个具有专门化的“enforcer”类,如下所示:

#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");
};

为了保持界面的简单,您可以通过专门化扩展
存储
,它提供诸如
unique\u 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){ ... }  // 
};

这里有一个。

我注意到tweak_enforcer需要3个参数。它能仅仅是两个类似的
tweak\u enforcer
?例如,在类的作用域中,我知道
TWeak=int*
T=std::unique_ptr
,但我不知道如何“访问”
int
@javaLover如果我理解正确,我同意;开始将其作为traits类编写,该类接受两个参数,并将
type
定义为它应该是什么。问题是,对应关系不是1:1。在这种情况下,1个类型与2个可接受的类型匹配。我所知道的唯一方法是将
type
定义为某种类型的类型列表,这非常麻烦。使用unique\u ptr应该添加什么?拥有所有权?如果是这样,为什么不改为使用add(T&&)函数呢?@rubenvb是的,假设所有权。创建一个函数
add(T&&)
是可以的,但我认为它并不能解决规则执行的问题。首先,问问自己:为什么要制定这些规则?然后,看看它是否可以不使用。然后,检查std::vector的实现,看看它是如何处理这些事情的。如果这还不能解决问题,请使用
std::is\u same
添加一些
static\u assert
s来强制执行带有明确错误消息的规则。不过,这些转换很可能已经由编译器强制执行。@rubenvb(1)当我检查
std::vector
时,我发现了限制,因此,我假设
std::vector
不是一个好例子。。。。(2) 关于静态断言,我没有足够的天赋。“Ami Tavory”试图做到这一点(下面的答案),但没有完成,因为它很麻烦。。。(3) 关于“已经被执行”,如果我自己也能控制它,我会更高兴。我不喜欢有关模板的不可读编译器错误。通过原始指针删除唯一的\u ptr意味着可能还有其他原始指针指向已删除的对象,这与您对该对象所有权的任何保证相矛盾。这是灾难的秘诀。我强烈建议你重新思考你在做什么。哇!我不知道我能这样推导出来。编译器如何知道选择哪一个-
Storage
vs
Storage
?所谓的技术是什么(同一类,但有不同的
)。。。模板专门化?(也就是说,我在哪里可以找到更多信息?@javaLover,实际上编译器有自己的方法来找到模板专门化的最佳匹配。在这种情况下,这是直截了当的。您正在传递
unique\u ptr
,因此选择了相同的类专门化。在这种情况下,如果您希望传递
共享的\u ptr
或其他包装,而不是
唯一的\u ptr
,那么还有一种方法。我们需要稍微修改一下专门的类定义。我会在同一天更新我的答案。
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; }
}   
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<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*/);