我对c ++模板有疑问。
template <class Container>
void tryTriggers(const Container& entities)
{
for (Container::const_iterator ent = std::begin(entities);ent != std::end(entities); ++ent)
{
if ((*ent)->isReadyForTriggerUpdate() && (*ent)->isAlive())
{
for (TriggerList::const_iterator trg = std::begin(_triggers);trg != std::end(_triggers); ++trg)
{
//Try(..) is a method takes *entity(entity's pointer) for parameters.
//But my container was implemented with unique_ptr.
//ex) vector<unique_ptr<entity>> v;
//So I used get() method for acquire raw pointer.
(*trg)->Try((*ent).get());
}
}
}
}
代码是某些容器的模板成员函数。
它仅适用于其中包含isReadyForTriggerUpdate()
和isAlive()
的班级。
Try(..)
是一种方法需要*entity(entity's pointer)
参数。
在我的情况下,我使用unique_ptr
int容器,所以我必须使用get()
方法来获取原始指针。
该函数不会产生任何问题,但是..如果我使用带有原始指针的容器,如
vector <entity*> v;
然后就会出问题。
问题: 我想让它更通用,以便它可以使用原始指针和智能指针。对此有什么解决方法吗?
在 STL 中,std::begin(con)
用于解决与con.begin()
中的迭代问题相关的问题。所以我希望有一些通用的方法,比如
std::begin(con)
针对上述问题。
答案 0 :(得分:3)
除了@Slava的非常正确的答案之外,你通常可以总是编写一个模板函数并将其专门用于原始指针:
template<class T>
auto find_address_of(T &&p) -> decltype(p.get())
{
return p.get();
}
template<typename T>
T *find_address_of(T *p)
{
return p;
}
答案 1 :(得分:1)
如果您使用解除引用的指针的地址而不是在两种情况下都应该工作的std::unique_ptr::get()
:
(*trg)->Try(&**ent);
答案 2 :(得分:0)
(*ent).get()
由于我对您的其他程序一无所知,我认为这是阻止您的函数工作的唯一行:get
是智能指针的成员函数,但它可以&#39 ; t与原始指针一起使用。我看到有两种解决方案可以解决这个问题:
解决方案1
使您的Try
函数可以使用智能指针和原始指针。例如:
class A
{
public:
template <class SmartPointer>
void Try(const SmartPointer& pointer)
{
Try(pointer.get());
}
void Try(entity* pointer)
{
/* Your code here */
}
}
解决方案2
如果您无法更改正在使用的类,那么您可以创建一些函数将您正在处理的抽象类型转换为原始指针。一个用于智能指针的函数和一个用于原始指针的函数。
template <class SmartPointer>
typename SmartPointer::element_type* getRawPointer(Pointer const& p)
{
return p.get();
}
template <typename T>
T* getRawPointer(T* p)
{
return p;
}
其中SmartPointer::element_type
是智能指针使用的类型(int
为std::unique_ptr<int>
)。请注意,您必须将其声明为typename SmartPointer::element_type
,以告诉编译器这确实是一种类型。
修改:将SmartPointer::pointer
更改为SmartPointer::element_type*
,使其与更新的智能指针配合使用。