Специфическая специализация шаблона C ++ - PullRequest
0 голосов
/ 30 января 2012

У меня есть следующий фрагмент кода:

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>, с Т может быть или не быть производным от IRunnable. Я получаю следующую ошибку компилятора (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> >*'

Почему ServicePtrDeleter::operator() создается с ServicePtr< ServicePtr<T> >? Я просто хочу получить T внутри operator(), чтобы я мог проверить, реализует ли он IRunnable или нет.

main.cc: 114 - это auto logWriter=LogWriter::create(); Это глобальная переменная.

class LogWriter:
        public ServiceCreator<LogWriter>,
        public IRunnable<LogWriter>,
{
....
}

1 Ответ

3 голосов
/ 30 января 2012

ServicePtrDeleter создается здесь:

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

Параметр шаблона, заданный для ServicePtrDeleter, равен ServicePtr<T>.

Когда вы заменяете параметр шаблона на ServicePtr<T> in operator() из ServicePtrDeleter, в итоге вы получите параметр ServicePtr< ServicePtr<T> >.

Возможно, вы просто хотели использовать в шаблоне параметр шаблона T, поскольку ServicePtrDeleter превращает его в ServicePtrсам:

... servicePtr(new ServicePtr<T>, ServicePtrDeleter<T>());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...