模板推断与智能指针

时间:2014-09-08 14:32:57

标签: c++ templates pointers

我的代码如下所示:

#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

3 个答案:

答案 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)

但是,正如其他人所说,你可能不需要这个。只是让模板参数推断发生而不是拼写出来。