2011-01-17 2 views
4

вопрос является своего рода трудно спросить без примера, так вот оно:Typedef эквивалентности аргументов функции

#include <vector> 

struct O 
{ 
}; 

struct C 
{ 
    template <typename T> 
    void function1(void (C::*callback)(const O*)); 

    template <typename T> 
    void function2(void (C::*callback)(const typename T::value_type)); 

    void print(const O*); 
}; 


int main() 
{ 
    C c; 

    c.function1< std::vector<O*> >(&C::print); // Success. 
    c.function2< std::vector<O*> >(&C::print); // Fail. 
} 

ошибка, что я даюсь это:

error: no matching function for call to ‘C::function2(void (C::*)(const O*))’.

В принципе, единственное различие между вызовами является то, что в function2, я более общий характер, так как я использую ЬурейеЕ std::vector<O*>::value_type который должен решить для O*, следовательно, подобный function1.

Я использую G ++ 4.2.1 (я знаю, что он старый), но Комо подтверждает, что я неправ.

Почему компиляция не удалась?

+3

О, я начинаю думать, что 'const typename T :: value_type' не разрешает' const O * ', а' O * const'. Как я могу достичь того, чего хочу? –

+1

Точно. Используйте свойства, чтобы добавить константу. –

ответ

4

Ваша проблема заключается в том, что const typename T::value_type в основном typename T::value_type const, который решает O* const, которые, очевидно, не то же самое, как const O* (что было бы O const *, при написании заявления PTR за типа (более полезным, чтобы выяснить это поведение)).

Что касается архивирования, что вы хотите, это зависит от того, что вы хотите. Если вы хотите, вы можете использовать boost type_traits или tr1 type_traits раздеться указатель, добавить сопзЬ и сделать его указатель снова, как это:

template <typename T> 
void function2(void (C::*callback)(typename boost::add_pointer<typename boost::add_const<typename boost::remove_pointer<typename T::value_type>::type>::type>::type)); 

Использование tr1 вместо boost должны быть в основном вопрос замены boost:: с std::tr1::.

Однако я бы не стал называть это полезным обобщением, поэтому вам может потребоваться переутомление, если вы действительно хотите идти этим путем. Лично я либо использовал бы что-то вроде boost function, либо бесплатные функции как обратные вызовы, первый из которых позволяет гораздо большую гибкость в том, что можно использовать в качестве обратных вызовов (бесплатные функции, функторы, функции-члены), а позднее, по крайней мере, упрощает создание второго функцию, которая соответствующим образом преобразует аргументы (т. е. если вы хотите использовать функцию, которая получает параметр const O* в качестве параметра, вы можете создать тот, который принимает O* и вызывает первый с этим параметром и использует его как обратный вызов).

+0

Указатель функции-члена, целью которого является то же, что и вызывающий, требуется только '& C :: print'. 'Boost :: function' требует' boost :: bind (& C :: print, this) '. Так что это «легче». Более того, это ничего не решит, так как обратный вызов все еще нуждается в аргументе, тип которого зависит от имени шаблона. –

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