2012-01-30 6 views
0

У меня есть следующий фрагмент кода:Удельное C++, шаблон специализации

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 is auto logWriter=LogWriter::create(); Это глобальная переменная.

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

А в чем вопрос? (Измените свой вопрос и добавьте прямой вопрос до конца) – Vyktor

+0

Теперь я исправляю вопрос. Вы, ребята, слишком быстро. –

+0

В main.cc, как вы используете эти классы? Можете ли вы показать нам код вокруг строки 114 (откуда возникает ошибка)? –

ответ

3

ServicePtrDeleter инстанциируется здесь:

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

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

Если вы замените параметр шаблона ServicePtr<T> на номер operator() из ServicePtrDeleter, вы получите параметр ServicePtr< ServicePtr<T> >.

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

... servicePtr(new ServicePtr<T>, ServicePtrDeleter<T>()); 
+0

OMG. Да, это исправляет ошибку компиляции, и на первый взгляд работает. Прежде чем я вернусь к этому вопросу, вы можете объяснить, почему opetator() (ServicePtr *) не получил специализированных. Насколько я понимаю, система типов C++ выбирает наиболее подходящее совпадение. Когда я передаю ServicePtr * оператору(), не должен ли C++ понимать, что это согласовано и извлечь T из него? Или я просто ошибаюсь: –

+0

Это связано с тем, что вы пытаетесь специализировать или создавать экземпляр struct/class, а не функцию шаблона ... с шаблоном struct/class, нет соответствующего участия, если вы специально не создаете отдельный специализированный struct/class со специальными параметрами шаблона. Например, 'template <> struct ServiceCreator {...};'. Кроме того, компилятор C++ не может выводить параметры шаблона из возвращаемого типа, только из аргументов в функцию, поэтому, даже если вы создали 'create' функцию шаблона, вам нужно будет указать аргументы шаблона. – Jason

+0

В этом нет никакой специализации. У вас есть только шаблон класса, который при создании экземпляра с некоторым типом 'X' будет иметь' void operator() (ServicePtr *) const'. Неважно, какой тип 'X'. – sth

Смежные вопросы