我的代码如下所示:
#include <iostream>
#include <memory>
using namespace std;
class myClass
{
int a;
};
template <typename T, template<typename ValueType> class SmartPtr> // (1)
void myFunction(const void *pointer, SmartPtr<T>& pointer2)
{
cout<<"with template"<<endl;
}
void myFunction(const void *pointer, unique_ptr<myClass>& pointer2)
{
cout<<"without template "<< *(static_cast<const int*>(pointer))<<endl;
}
int main()
{
int* a = new int(5);
unique_ptr<myClass> myUniquePtr(new myClass);
shared_ptr<myClass> mySharedPtr(new myClass);
myFunction(static_cast<const void*>(a), myUniquePtr); // (2)
myFunction<int, unique_ptr<myClass> >(static_cast<const void*>(a), myUniquePtr); // (3)
myFunction<int, shared_ptr<myClass> >(static_cast<const void*>(a), mySharedPtr); // (4)
delete a;
return 0;
}
在(2)中调用'myFunction'是可以的 - 它在没有模板的情况下调用'myFunction'。但是在(3)和(4)中编译器不能推导出模板参数。它会产生错误:
no matching function for call to ‘myFunction(const void*, std::unique_ptr<myClass>&)'
和
no matching function for call to ‘myFunction(const void*, std::shared_ptr<myClass>&)'
分别。
问题是如何在(1)中更改模板的第二个参数,以便我可以使用任意智能指针实例化模板?我想省略ValueType
并使用T
。
答案 0 :(得分:8)
不需要有两个模板参数,这将导致使用自定义分配器的智能指针出现问题。只需要一个模板参数:智能指针的类型。
template <typename T>
void myFunction(const void *pointer, T & pointer2)
{
}
所以T
是智能指针类型。如果您需要访问托管对象的类型(在本例中为myClass
),则可以使用typename std::pointer_traits<T>::element_type
。
template <typename T>
void myFunction(const void *pointer, T & pointer2)
{
typedef typename std::pointer_traits<T>::element_type obj_type;
obj_type & o = *pointer2;
}
(当然,如果你使用的是C ++ 11,你也可以使用decltype(*pointer2)
甚至auto
。)
使用这种方法,您甚至可以将原始指针用作T
,假设您的逻辑都不依赖于它们是智能指针。
作为旁注,您的调用可能会失败,因为您提供int
作为T
模板参数,这没有任何意义;你应该在那里使用myClass
。
答案 1 :(得分:2)
我们有template <class T, class D = default_delete<T>> class unique_ptr;
因此,您的功能模板应如下所示:
template <template<typename, typename> class SmartPtr, typename T, typename D>
void myFunction(const void *pointer, SmartPtr<T, D>& pointer2)
{
std::cout << "with template" << std::endl;
}
但使用像cdhowie的回答可能更简单。
答案 2 :(得分:0)
它抱怨的原因是因为你给它一个类型作为第二个模板参数,但它需要一个模板(因为你使用了模板模板语法。)以下应该至少让它超过模板扩展步骤编译(警告,未编译,但你应该得到这个想法)
myFunction<int, unique_ptr>(static_cast<const void*>(a), myUniquePtr); // (3)
myFunction<int, shared_ptr>(static_cast<const void*>(a), mySharedPtr); // (4)
但是,正如其他人所说,你可能不需要这个。只是让模板参数推断发生而不是拼写出来。