2016-10-15 35 views
0

我不能任何好的解决方案。我有一段代码:'std :: result_of <_Signature> :: type'之前需要'typename',因为'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; 
} 

编辑:你在这里头

#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; 

我尝试使用的result_of之前添加类型名称,但它造成其他错误:“无效使用类型......”。

我想要像你在主函数中看到的东西。我想添加新的任务,像线程池。模板参数应该尽可能少地给出。完美的解决方案正在推演:-)。

+0

err或者由于错过标题而不可重现。你应该创造一个最小的例子。 – skypjack

+0

您正在使用'result_of'错误。 –

+0

@ T.C:是的,“如果你有错误,修复它,它会被修复!”。它根本不起作用。编译器告诉我,我知道我错误地使用了它。我只是试着找出如何正确使用它或只是使用其他的东西。 –

回答

1

result_of<>你不仅要传递函数的类型(在你的情况下为T),还要传递参数的类型。所以,如果我理解你的意图,你的Callable类也应该收到一个可变参数列表(说ArgsT)并使用它们(std::result_of<T(ArgsT...)>::type)。

换句话说,我想,你的Callable类应该在Task

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 ...); 
    } 
}; 

,并通过实例,应该被称为

Callable<CallableType, ArgType...> m_callable; 

result_of<>其他用途相同的解决方案:通到类型函数的arg类型

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

看来我需要验证项目假设,并不是所有的都可以调和。但是,谢谢你的线索。 –

相关问题