2016-10-15 12 views
0

Я не могу найти подходящего решения. У меня есть кусок кода:Need 'typename' before 'std :: result_of <_Signature> :: type' потому что 'std :: result_of <_Signature>' является зависимым областью

#include <iostream> 
#include <future> 
#include <memory> 
#include <functional> 
#include <cstddef> 
#include <tuple> 
#include <typeinfo> 
#include <queue> 
#include <type_traits> 
#include "threadsafe_queue.hpp" 

using namespace std; 

template<int ...> 
struct seq { }; 

template<int N, int ...S> 
struct gens : gens<N-1, N-1, S...> { }; 

template<int ...S> 
struct gens<0, S...> { 
    typedef seq<S...> type; 
}; 

class JoinThreads { 
    vector<std::thread>& m_threads; 
public: 
    explicit JoinThreads(vector<std::thread>& threads): m_threads(threads) {} 

    ~JoinThreads() { 
     for (unsigned long a = 0; a < this-> m_threads.size(); a++) { 
      if (this->m_threads[a].joinable()) { 
       this->m_threads[a].join(); 
      } 
     } 
    } 

}; 

template<typename T> 
class Callable { 
    T m_proc; 
public: 
    Callable() {} 

    Callable(T proc): m_proc(proc) { 
     // 
    } 

    template<typename ... V> 
    typename std::result_of<T>::type Call(V ... args) { 
     return this-> m_proc(args ...); 
    } 

}; 

template<typename ResultType> 
class TaskResult { 
    ResultType m_result; 
public: 
    TaskResult(ResultType result) {} 
    ResultType result() const { 
     return this-> m_result; 
    } 
}; 

template<typename CallableType, typename ... ArgType> 
class Task { 
    Callable<CallableType> m_callable; 
    std::tuple<ArgType...> m_args; 
    void (*m_callback)(TaskResult<CallableType>); 

    template<int ...S> 
    typename std::result_of<CallableType>::type invokeCallable(seq<S...>) { 
     return this-> m_callable.Call(std::get<S>(this-> m_args) ...); 
    } 
protected: 
    typedef typename std::result_of<CallableType>::type callableType; 
public: 
    Task() {} 

    Task(Callable<CallableType> callable, ArgType ... args, TaskResult<CallableType> callback): m_callable(callable), m_callback(callback) { 
     this-> m_args = std::make_tuple(args ...); 
    } 

    void Execute() { 
     typename std::result_of<CallableType>::type result = this-> invokeCallable(typename gens<sizeof...(ArgType)>::type()); 
     void (*callback)(TaskResult<CallableType>) = reinterpret_cast<void (*)(TaskResult<CallableType>) >(this-> m_callback); 

     if (0 < (size_t)callback) { 
      this-> m_callback(TaskResult<CallableType>(result)); 
     } 
    } 
}; 

template<typename T> 
class Dequeue { 
    threadsafe_queue<T> m_tasks; 
    std::vector<std::thread> m_threads; 
    std::atomic_bool m_done; 
    JoinThreads m_joiner; 
    void Process() { 
     typename threadsafe_queue<T>::m_size_type size = 0; 
     while (!m_done) { 
      T task; 
      if (this-> m_tasks.try_pop(task)) { 
       task.Execute(); 
      } else { 
       std::this_thread::yield(); 
      } 
     } 
    } 
public: 
    Dequeue(unsigned threads = 0): m_done(false), m_joiner(m_threads) { 
     unsigned const threadCount = threads > 0 ? threads : std::thread::hardware_concurrency(); 

     cout << "Threads count: " << threadCount << endl; 

     try { 
      for (unsigned i = 0; i < threadCount; ++i) { 
       this-> m_threads.push_back(std::thread(&Dequeue::Process, this)); 
      } 
     } catch (...) { 
      this-> m_done = true; 
      throw; 
     } 
    } 

    ~Dequeue() { 
     this-> m_done = true; 
    } 

    template<typename CallableType, typename CallbackType, typename ... ArgType> 
    void Subscribe(CallableType callable, CallbackType callback, ArgType ... args) { 
     this-> m_tasks.push(Task<CallableType, CallbackType, ArgType...> (callable, args ..., callback)); 
    } 

    void Subscribe(T task) { 
     this-> m_tasks.push(task); 
    } 

}; 


template<typename CallableType, typename CallbackType, typename ... ArgType> 
Task<CallableType, CallbackType, ArgType ...> SubscribeTask(CallableType callable, CallbackType callback, ArgType ... args) { 
    return Task<CallableType, CallbackType, ArgType...> (callable, args ..., callback); 
} 

int foo(int a, int b) { 
    int N = 1024, tab[N], z = 0; 
    //Some long task 
    return tab[0]; 
} 

void callback(TaskResult<int (*)(int, int)> res) { 
    cout << "Callback" << endl; 
} 

/* 
* Callback jednak warto zrobić z parametrem jako obiekt jakiegoś zdarzenia i 
* nie wymuszać konieczności podania parametru szablonu. 
*/ 

int main() { 
    cout << "Hello world!" << endl; 
    Dequeue<Task<int (*)(int, int), int, int> > dequeue(4); 
    cout << "Pushing tasks..." << endl; 
    dequeue.Subscribe(foo, callback, 2156, 55); 
    for (int a = 0; a < 1024; a++) { 
     for (int b = 0; b < 1024; b++) { 
      dequeue.Subscribe(foo, callback, a, b); 
     } 
    } 

    cout << "Processing..." << endl; 
    int a; 
    cin >> a; 
    return 0; 
} 

EDIT: здесь вы заголовок

#include <mutex> 
#include <condition_variable> 
#include <queue> 
#include <memory> 

template<typename T> 
class threadsafe_queue { 
private: 
    mutable std::mutex mut; 
    std::queue<T> data_queue; 
    std::condition_variable data_cond; 
public: 
    typedef 
    typename 
    std::queue<T>::size_type m_size_type; 
    threadsafe_queue() { 
    } 
    threadsafe_queue(threadsafe_queue const& other) { 
     std::lock_guard <std::mutex> lk(other.mut); 
     data_queue = other.data_queue; 
    } 

    void push(T new_value) { 
     std::lock_guard <std::mutex> lk(mut); 
     data_queue.push(new_value); 
     data_cond.notify_one(); 
    } 

    void wait_and_pop(T& value) { 
     std::unique_lock <std::mutex> lk(mut); 
     data_cond.wait(lk, [this] {return !data_queue.empty();}); 
     value = data_queue.front(); 
     data_queue.pop(); 
    } 

    std::shared_ptr<T> wait_and_pop() { 
     std::unique_lock <std::mutex> lk(mut); 
     data_cond.wait(lk, [this] {return !data_queue.empty();}); 
     std::shared_ptr<T> res(std::make_shared <T> (data_queue.front())); 
     data_queue.pop(); 
     return res; 
    } 

    bool try_pop(T& value) { 
     std::lock_guard <std::mutex> lk(mut); 
     if (data_queue.empty()) 
      return false; 
     value = data_queue.front(); 
     data_queue.pop(); 
     return true; 
    } 

    std::shared_ptr<T> try_pop() { 
     std::lock_guard <std::mutex> lk(mut); 
     if (data_queue.empty()) 
      return std::shared_ptr<T>(); 
     std::shared_ptr<T> res(std::make_shared <T> (data_queue.front())); 
     data_queue.pop(); 
     return res; 
    } 

    bool empty() const { 
     std::lock_guard <std::mutex> lk(mut); 
     return data_queue.empty(); 
    } 

    m_size_type size() const { 
     std::lock_guard <std::mutex> lk(mut); 
     return data_queue.size(); 
    } 
}; 

У меня есть ошибка:

main.cpp: In instantiation of ‘class Callable<int (*)(int, int)>’: 
main.cpp:69:25: required from ‘class Task<int (*)(int, int), void (*)(TaskResult<int (*)(int, int)>), int, int>’ 
main.cpp:135:3: required from ‘void Dequeue<T>::Subscribe(CallableType, CallbackType, ArgType ...) [with CallableType = int (*)(int, int); CallbackType = void (*)(TaskResult<int (*)(int, int)>); ArgType = {int, int}; T = Task<int (*)(int, int), int, int>]’ 
main.cpp:175:43: required from here 
main.cpp:51:35: error: invalid use of incomplete type ‘class std::result_of<int (*)(int, int)>’ 
    typename std::result_of<T>::type Call(V ... args) { 
           ^
In file included from /usr/include/c++/4.9/bits/move.h:57:0, 
       from /usr/include/c++/4.9/bits/stl_pair.h:59, 
       from /usr/include/c++/4.9/bits/stl_algobase.h:64, 
       from /usr/include/c++/4.9/bits/char_traits.h:39, 
       from /usr/include/c++/4.9/ios:40, 
       from /usr/include/c++/4.9/ostream:38, 
       from /usr/include/c++/4.9/iostream:39, 
       from main.cpp:1: 
/usr/include/c++/4.9/type_traits:2060:11: error: declaration of ‘class std::result_of<int (*)(int, int)>’ 
    class result_of; 
     ^
main.cpp: In instantiation of ‘class Task<int (*)(int, int), void (*)(TaskResult<int (*)(int, int)>), int, int>’: 
main.cpp:135:3: required from ‘void Dequeue<T>::Subscribe(CallableType, CallbackType, ArgType ...) [with CallableType = int (*)(int, int); CallbackType = void (*)(TaskResult<int (*)(int, int)>); ArgType = {int, int}; T = Task<int (*)(int, int), int, int>]’ 
main.cpp:175:43: required from here 
main.cpp:74:46: error: invalid use of incomplete type ‘class std::result_of<int (*)(int, int)>’ 
    typename std::result_of<CallableType>::type invokeCallable(seq<S...>) { 
              ^
In file included from /usr/include/c++/4.9/bits/move.h:57:0, 
       from /usr/include/c++/4.9/bits/stl_pair.h:59, 
       from /usr/include/c++/4.9/bits/stl_algobase.h:64, 
       from /usr/include/c++/4.9/bits/char_traits.h:39, 
       from /usr/include/c++/4.9/ios:40, 
       from /usr/include/c++/4.9/ostream:38, 
       from /usr/include/c++/4.9/iostream:39, 
       from main.cpp:1: 
/usr/include/c++/4.9/type_traits:2060:11: error: declaration of ‘class std::result_of<int (*)(int, int)>’ 
    class result_of; 
     ^
main.cpp:78:54: error: invalid use of incomplete type ‘class std::result_of<int (*)(int, int)>’ 
    typedef typename std::result_of<CallableType>::type callableType; 
                ^
In file included from /usr/include/c++/4.9/bits/move.h:57:0, 
       from /usr/include/c++/4.9/bits/stl_pair.h:59, 
       from /usr/include/c++/4.9/bits/stl_algobase.h:64, 
       from /usr/include/c++/4.9/bits/char_traits.h:39, 
       from /usr/include/c++/4.9/ios:40, 
       from /usr/include/c++/4.9/ostream:38, 
       from /usr/include/c++/4.9/iostream:39, 
       from main.cpp:1: 
/usr/include/c++/4.9/type_traits:2060:11: error: declaration of ‘class std::result_of<int (*)(int, int)>’ 
    class result_of; 
     ^
main.cpp: In instantiation of ‘void Dequeue<T>::Subscribe(CallableType, CallbackType, ArgType ...) [with CallableType = int (*)(int, int); CallbackType = void (*)(TaskResult<int (*)(int, int)>); ArgType = {int, int}; T = Task<int (*)(int, int), int, int>]’: 
main.cpp:175:43: required from here 
main.cpp:135:3: error: no matching function for call to ‘Task<int (*)(int, int), void (*)(TaskResult<int (*)(int, int)>), int, int>::Task(int (*&)(int, int), int&, int&, void (*&)(TaskResult<int (*)(int, int)>))’ 
    this-> m_tasks.push(Task<CallableType, CallbackType, ArgType...> (callable, args ..., callback)); 
^
main.cpp:135:3: note: candidates are: 
main.cpp:82:2: note: Task<CallableType, ArgType>::Task(Callable<CallableType>, ArgType ..., TaskResult<CallableType>) [with CallableType = int (*)(int, int); ArgType = {void (*)(TaskResult<int (*)(int, int)>), int, int}] 
    Task(Callable<CallableType> callable, ArgType ... args, TaskResult<CallableType> callback): m_callable(callable), m_callback(callback) { 
^
main.cpp:82:2: note: candidate expects 5 arguments, 4 provided 
main.cpp:80:2: note: Task<CallableType, ArgType>::Task() [with CallableType = int (*)(int, int); ArgType = {void (*)(TaskResult<int (*)(int, int)>), int, int}] 
    Task() {} 
^
main.cpp:80:2: note: candidate expects 0 arguments, 4 provided 
main.cpp:68:7: note: constexpr Task<int (*)(int, int), void (*)(TaskResult<int (*)(int, int)>), int, int>::Task(const Task<int (*)(int, int), void (*)(TaskResult<int (*)(int, int)>), int, int>&) 
class Task { 
    ^
main.cpp:68:7: note: candidate expects 1 argument, 4 provided 
main.cpp:68:7: note: constexpr Task<int (*)(int, int), void (*)(TaskResult<int (*)(int, int)>), int, int>::Task(Task<int (*)(int, int), void (*)(TaskResult<int (*)(int, int)>), int, int>&&) 
main.cpp:68:7: note: candidate expects 1 argument, 4 provided 
main.cpp: In instantiation of ‘class Task<int (*)(int, int), int, int>’: 
main.cpp:105:6: required from ‘void Dequeue<T>::Process() [with T = Task<int (*)(int, int), int, int>]’ 
main.cpp:121:44: required from ‘Dequeue<T>::Dequeue(unsigned int) [with T = Task<int (*)(int, int), int, int>]’ 
main.cpp:173:55: required from here 
main.cpp:74:46: error: invalid use of incomplete type ‘class std::result_of<int (*)(int, int)>’ 
    typename std::result_of<CallableType>::type invokeCallable(seq<S...>) { 
              ^
In file included from /usr/include/c++/4.9/bits/move.h:57:0, 
       from /usr/include/c++/4.9/bits/stl_pair.h:59, 
       from /usr/include/c++/4.9/bits/stl_algobase.h:64, 
       from /usr/include/c++/4.9/bits/char_traits.h:39, 
       from /usr/include/c++/4.9/ios:40, 
       from /usr/include/c++/4.9/ostream:38, 
       from /usr/include/c++/4.9/iostream:39, 
       from main.cpp:1: 
/usr/include/c++/4.9/type_traits:2060:11: error: declaration of ‘class std::result_of<int (*)(int, int)>’ 
    class result_of; 
     ^
main.cpp:78:54: error: invalid use of incomplete type ‘class std::result_of<int (*)(int, int)>’ 
    typedef typename std::result_of<CallableType>::type callableType; 
                ^
In file included from /usr/include/c++/4.9/bits/move.h:57:0, 
       from /usr/include/c++/4.9/bits/stl_pair.h:59, 
       from /usr/include/c++/4.9/bits/stl_algobase.h:64, 
       from /usr/include/c++/4.9/bits/char_traits.h:39, 
       from /usr/include/c++/4.9/ios:40, 
       from /usr/include/c++/4.9/ostream:38, 
       from /usr/include/c++/4.9/iostream:39, 
       from main.cpp:1: 
/usr/include/c++/4.9/type_traits:2060:11: error: declaration of ‘class std::result_of<int (*)(int, int)>’ 
    class result_of; 

Я пытался добавить TypeName перед использованием result_of, но это вызвало другую ошибку : «ivalid использование несжимаемого типа ...».

Я хочу иметь что-то подобное в главной функции. Я хочу добавить новые задачи к чему-то вроде пула потоков. Аргументы шаблонов следует указывать как можно меньше. Идеальное решение выводится на всех :-).

+0

Ошибка или не воспроизводится из-за пропущенного заголовка. Вы должны создать минимальный пример. – skypjack

+0

Вы используете 'result_of' wrong. –

+0

@ T.C .: Да, «Если у вас есть ошибка, исправьте ее, и она будет исправлена!». Это не работает вообще. Я знаю, что я использую это неправильно, компилятор сказал мне. Я просто пытаюсь выяснить, как использовать это право или просто использовать что-то еще. –

ответ

1

В result_of<> вам необходимо передать не только тип функции (T, в вашем случае), но и типы аргументов.

Так что, если я понимаю ваши намерения, ваш Callable класс должен также получить VARIADIC список аргументов (скажем ArgsT) и использовать их (std::result_of<T(ArgsT...)>::type).

Другими словами, я полагаю, что ваш Callable класс должен быть

template<typename T, typename ... ArgsT> 
class Callable { 
    T m_proc; 
public: 
    Callable() {} 

    Callable(T proc): m_proc(proc) { 
     // 
    } 

    template<typename ... V> 
    typename std::result_of<T(ArgsT...)>::type Call(V ... args) { 
     return this-> m_proc(args ...); 
    } 
}; 

и, например, в Task, следует назвать

Callable<CallableType, ArgType...> m_callable; 

То же решение с другими видами использования result_of<>: передача к типовой функции типы arg

typename std::result_of<CallableType(ArgType...)>::type 
+0

Кажется, мне нужно проверить предположения проекта, не все могут быть согласованы. Однако, спасибо за хорошую подсказку. –