0

I have the following code fragment:

template <class T> struct ServicePtr { std::shared_ptr<T> service; ~ServicePtr() { std::cout << __PRETTY_FUNCTION__ << std::endl; } }; template <class T> struct ServicePtrDeleter { void operator()(ServicePtr<T>* ref) const { if (ref->service.get()) { if (IRunnable<T>* r=dynamic_cast<IRunnable<T>*>(ref->service.get())) { //std::cout << "Mark Thread Finished" << std::endl; r->stop(); } else { std::cout << __FILE__ << ":" << __LINE__ << std::endl; } } delete ref; } }; template <typename T> struct ServiceCreator { static std::shared_ptr< ServicePtr<T> > create() { std::shared_ptr< ServicePtr<T> > servicePtr(new ServicePtr<T>, ServicePtrDeleter< ServicePtr<T> >()); servicePtr->service.reset(new T); if (IRunnable<T>* r=dynamic_cast<IRunnable<T>*>(servicePtr->service.get())) { r->setSelfPtr(std::dynamic_pointer_cast<IRunnable<T>>(servicePtr->service)); } else { std::cout << __FILE__ << ":" << __LINE__ << std::endl; } return servicePtr; } }; 

ServiceCreator<T> , with T may or may not be derivated from IRunnable. I get the following compiler error(GCC 4.6.1):

In file included from /usr/lib/gcc/i686-pc-linux-gnu/4.6.1/../.. /../../include/c++/4.6.1/bits/shared_ptr.h:52:0, from /usr/lib/gcc/i686-pc-linux-gnu/4.6.1/../../../../include/c++/4.6.1/memory:86, from /usr/lib/gcc/i686-pc-linux-gnu/4.6.1/../../../../include/c++/4.6.1/thread:40, from main.cc:2: /usr/lib/gcc/i686-pc-linux-gnu/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h: In constructor 'std::__shared_count<_Lp>::__shared_count(_Ptr, _Deleter) [with _Ptr = ServicePtr<LogWriter>*, _Deleter = ServicePtrDeleter<ServicePtr<LogWriter> >, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]': /usr/lib/gcc/i686-pc-linux-gnu/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h:771:37: instantiated from 'std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*, _Deleter) [with _Tp1 = ServicePtr<LogWriter>, _Deleter = ServicePtrDeleter<ServicePtr<LogWriter> >, _Tp = ServicePtr<LogWriter>, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]' /usr/lib/gcc/i686-pc-linux-gnu/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:128:37: instantiated from 'std::shared_ptr<_Tp>::shared_ptr(_Tp1*, _Deleter) [with _Tp1 = ServicePtr<LogWriter>, _Deleter = ServicePtrDeleter<ServicePtr<LogWriter> >, _Tp = ServicePtr<LogWriter>]' ServiceCreator.h:45:102: instantiated from 'static std::shared_ptr<ServicePtr<U> > ServiceCreator<T>::create() [with T = LogWriter]' main.cc:114:27: instantiated from here /usr/lib/gcc/i686-pc-linux-gnu/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h:480:8: error: no match for call to '(ServicePtrDeleter<ServicePtr<LogWriter> >) (ServicePtr<LogWriter>*&)' ServiceCreator.h:19:8: note: candidate is: ServiceCreator.h:21:7: note: void ServicePtrDeleter<T>::operator()(ServicePtr<T>*) const [with T = ServicePtr<LogWriter>] ServiceCreator.h:21:7: note: no known conversion for argument 1 from 'ServicePtr<LogWriter>*' to 'ServicePtr<ServicePtr<LogWriter> >*' 

Why ServicePtrDeleter::operator() gets instantiated with ServicePtr< ServicePtr<T> >? I just want to get T, inside operator(), so I can test whether it implements IRunnable or not.

main.cc:114 is auto logWriter=LogWriter::create(); It is a global variable.

class LogWriter: public ServiceCreator<LogWriter>, public IRunnable<LogWriter>, { .... } 
6
  • And what's the question? (Edit your question and add direct question to the end of it) Commented Jan 30, 2012 at 12:13
  • I am fixing the question now. You guys are just too quick. Commented Jan 30, 2012 at 12:16
  • In main.cc, how do you use these classes? Can you show us the code around line 114 (where the error originates)? Commented Jan 30, 2012 at 12:17
  • Any reason you have a shared_ptr inside a shared_ptr... ? Commented Jan 30, 2012 at 12:22
  • 1
    @DragomirIvanov: No, you pressed "Submit Question" too quickly. Commented Jan 30, 2012 at 12:23

1 Answer 1

3

ServicePtrDeleter is instantiated here:

std::shared_ptr< ServicePtr<T> > servicePtr(new ServicePtr<T>, ServicePtrDeleter< ServicePtr<T> >()); 

The template parameter given to ServicePtrDeleter is ServicePtr<T>.

When you replace the template parameter with ServicePtr<T> in operator() of ServicePtrDeleter, you end up with a ServicePtr< ServicePtr<T> > parameter.

You probably just wanted to use a T template parameter in the instantiation, since ServicePtrDeleter wraps that into a ServicePtr itself:

... servicePtr(new ServicePtr<T>, ServicePtrDeleter<T>()); 
Sign up to request clarification or add additional context in comments.

3 Comments

OMG. Yes, this fixes the compilation error, and on the first sight works. Before I this answer acceped, can you explain, why opetator()(ServicePtr<T>*), didn't got specialized. As I understand C++ typesystem it pick the most appropriate match. When I pass ServicePtr<T>* to operator(), shouldn't C++ understand that this is matched and extract T from it? Or I am just mistaken:
This is because you're attempting to specialize or instantiate a template struct/class rather than a template function ... with a struct/class template, there is no matching involved unless you specifically create a separate specialized struct/class with the specialized template parameters. For instance, template<> struct ServiceCreator<LogWriter> { ... };. Also the C++ compiler can't deduce the template parameters from the return type, only from the arguments to a function, so even if you made create a template function, you'd have to specify the template arguments.
There is no specialization involved. You have just a class template that, when instantiated with some type X, will have a void operator()(ServicePtr<X>*) const. It doesn't matter what type X is.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.