0
votes

I am trying to declare a function that checks wether a smart pointer is initialized. I wrote two variants of a function that acts on smart pointers, one template function acting on templates, one acting on a template of a template. The problem is, the latter one is supposed to act on at least std::unique_ptr and std::shared_ptr. The std::unique_ptr one is constructed differently from std::shared_ptr. std::unique_ptr one takes two template arguments (namely object type and deleter) whereas std::shared_ptr one takes only one (namely the object type).

#include <iostream>
#include <memory>


template <typename  Smartpointer>
void checkPointerinitialization(const Smartpointer& ptr){
    if(!ptr.get())
        std::cout<<"smart pointer is not initialized\n"<<std::endl;
}



//template <template <typename, typename> class Smartpointer, typename Object, typename Deleter>
//void checkPointerinitializationWithTemplates(const Smartpointer<Object, Deleter>& ptr){
//    if(!ptr.get())
//        std::cout<<"smart pointer is not initialized in template function either\n"<<std::endl;
//}
//int main(){
//    std::shared_ptr<int> myptr;
//    checkPointerinitialization(myptr);
//    checkPointerinitializationWithTemplates(myptr);
//
//}

template <template <typename> class Smartpointer, typename Object>
void checkPointerinitializationWithTemplates(const Smartpointer<Object>& ptr){
    if(!ptr.get())
        std::cout<<"smart pointer is not initialized in template function either\n"<<std::endl;
}
int main(){
    std::shared_ptr<int> myptr;
    checkPointerinitialization(myptr);
    checkPointerinitializationWithTemplates(myptr);

}

My solution was to overload the template function, however if I uncomment the first function, I get a template deduction failed - wrong number of template arguments error message from g++. Is it actually possible to overload the template functions in an appropriate manner?

1
std::shared_ptr has only one template parameter. melpon.org/wandbox/permlink/nugnyaHklfQfBzp1Danh

1 Answers

4
votes

Instead of taking your argument as an instantiation of a class template with one single template parameter, take your argument as a class template taking at least one template parameter:

template <template <class, class...> class Z,
    class Object,
    class... Ts>
void foo(const Z<Object, Ts...>& ptr) { ... }

This will match both std::unique_ptr<X> (with Object=X and Ts={std::default_delete<X>}) and std::shared_ptr<X> (with Object=X and Ts={}).


However, this will not match any non-template smart pointers, like:

struct MySpecialSnowflakeSmartPointer { ... };

So your first approach is probably best:

template <class SP>
void foo(SP const& ptr) { ... }