2010-04-29 2 views
9

Один из моих личных экспериментов для понимания некоторых функций C++ 0x: Я пытаюсь передать указатель на функцию шаблона для выполнения. В конце концов выполнение должно происходить в другом потоке. Но со всеми различными типами функций я не могу заставить шаблоны работать.Шаблоны, указатели функций и C++ 0x

#include <functional> 

int foo(void) {return 2;} 

class bar { 
public: 
    int operator() (void) {return 4;}; 
    int something(int a) {return a;}; 
}; 

template <class C> 
int func(C&& c) 
{ 
    //typedef typename std::result_of< C() >::type result_type; 
    typedef typename std::conditional< 
     std::is_pointer<C>::value, 
     std::result_of< C() >::type, 
     std::conditional< 
      std::is_object<C>::value, 
      std::result_of< typename C::operator() >::type, 
      void> 
     >::type result_type; 
    result_type result = c(); 
    return result; 
} 

int main(int argc, char* argv[]) 
{ 
    // call with a function pointer 
    func(foo); 

    // call with a member function 
    bar b; 
    func(b); 

    // call with a bind expression 
    func(std::bind(&bar::something, b, 42)); 

    // call with a lambda expression 
    func([](void)->int {return 12;}); 

    return 0; 
} 

Шаблон result_of в одиночку, кажется, не сможет найти оператор() в классе бар и неуклюжим условный я создал не компилируется. Есть идеи? У меня возникнут дополнительные проблемы с функциями const?

+0

Возможно, причина, по которой он не компилируется, заключается в том, что 'func' возвращает' int' вместо 'result_type' (который в этом примере является' int' во всех случаях, но может все еще вызвать проблему)? –

+0

@ Крис: Нет, это не причина. – kennytm

+0

@KennyTM - Я не думал, но все же думаю, что это проблема. –

ответ

6

Как об использовании decltype?

template <class C> 
auto func(C&& c) -> decltype(c()) { 
    auto result = c(); 
    return result; 
} 
+0

который выглядит намного чище. Благодаря! – user328543

4

Если я понимаю, проект C++ 0x право следующее должно быть на самом деле достаточно:

typedef typename std::result_of<C()>::type result_type; 

Пользуясь тем, что вместо вашего условного выражения, он компилирует штрафа на gcc4.5 - может быть, у вас есть нашел ошибку в любом компиляторе, который вы используете?

+0

вот что я тоже думал, но он не компилировался. Весь комплекс условный был создан, чтобы обойти это. – user328543

+1

@ user328543: Если я закомментирую ваше условное выражение и использую ранее прокомментированную строку, он компилируется абсолютно точно на gcc4.5. –

2

Я получил ваш шаблон для создания экземпляра, но GCC жалуется на возможное использование result_of.

template <class C> 
int func(C&& c) 
{ 
    //typedef typename std::result_of< C() >::type result_type; 
    typedef typename std::conditional< 
     std::is_pointer<C>::value, 
     // C++0x still requires "typename" sprinkles: 
     typename std::result_of< C() >::type, 
     typename std::conditional< 
      std::is_object<C>::value, 
      // result_of takes a *type* as an argument, not an object: 
      //typename std::result_of< decltype(&C::operator()) >::type, 
      // Or better: 
      typename std::result_of<C>::type, 
      void> 
     >::type result_type; 
    result_type result = c(); 
    return result; 
} 

int main(int argc, char* argv[]) 
{ 
    // according to GCC, func(foo) passes a function reference. 
    func(foo); 

Первое сообщение об ошибке:

rof.cpp:23:17: error: invalid use of incomplete type 'struct std::result_of<int (&)()>' 

result_of осуществляется, как указано в стандарте, так что кажется, что GCC не может соответствовать синтаксису псевдо-прототип в объявлении частичной специализации.

+0

Ссылки на функции должны работать: * «Fn - это тип объекта функции (20.8), ссылка на функцию или ссылка на тип объекта функции». * –

+1

@gf: классно, я сохраню комментарий как полезный педантичный. В любом случае сообщение об ошибке GCC ясно показывает, что оно отклоняет хороший код. – Potatoswatter

+0

@gf: неправильная нить? – Potatoswatter

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