Passing function as universal reference? Why?
Unsolved
C++ Gurus
-
Why
Functor&& f
is possed as universal ref? this is the function, when the function can become a rvalue?/** * Calls function <code>f</code> in this thread and returns a future<T> that can * be used to wait on the result. * * @param f the operation to perform * @param prio the priority relative to other tasks */ template<typename Functor> auto async( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future<decltype(f())> { typedef decltype(f()) Result; typedef typename fc::deduce<Functor>::type FunctorType; fc::task<Result,sizeof(FunctorType)>* tsk = new fc::task<Result,sizeof(FunctorType)>( fc::forward<Functor>(f), desc ); fc::future<Result> r(fc::shared_ptr< fc::promise<Result> >(tsk,true) ); async_task(tsk,prio); return r; }
-
Take this functor:
class ExampleFunctor { int* m_longArray; int m_longArraySize; public: ExampleFunctor(int sz = 10000) :m_longArraySize(sz) { if (m_longArraySize < 10000) m_longArraySize = 10000; m_longArray = new int[m_longArraySize]; for (int i = 0; i < m_longArraySize; ++i) m_longArray[i] = rand(); } ~ExampleFunctor() { if (m_longArray) delete[] m_longArray; } ExampleFunctor(const ExampleFunctor& other) :m_longArraySize(other.m_longArraySize) , m_longArray(new int[other.m_longArraySize]) { for (int i = 0; i < m_longArraySize; ++i) m_longArray[i] = other.m_longArray[i]; } ExampleFunctor(ExampleFunctor&& other) :m_longArraySize(other.m_longArraySize) , m_longArray(other.m_longArray) { other.m_longArray = nullptr; } ExampleFunctor& operator=(ExampleFunctor&& other) { m_longArraySize = other.m_longArraySize; std::swap(other.m_longArray, m_longArray); return *this; } ExampleFunctor& operator=(const ExampleFunctor& other) { if (m_longArray) delete[] m_longArray; m_longArraySize = other.m_longArraySize; m_longArray = new int[m_longArraySize]; for (int i = 0; i < m_longArraySize; ++i) m_longArray[i] = other.m_longArray[i]; return *this; } int operator()() { int result = 0; for (int i = 0; i < m_longArraySize - 1; ++i) result += (m_longArray[i] ^= m_longArray[i + 1]); return result; } static ExampleFunctor createFunctor(int size) { return ExampleFunctor(size); } };
Pass it to your template
async(ExampleFunctor::createFunctor(1000000));
Let's see what happens in each case:
auto async(Functor f
: takes a deep copy of the functorauto async(const Functor& f
: if you want to call the functor (since it's not const) you'll have to take a deep copy of it sooner or laterauto async(Functor& f
: this would work in the example above but ifoperator()()
was const and you create it withconst ExampleFunctor temp(1000000);
then you can't pass it anymoreauto async(Functor&& f
: accepts all kind of arguments without compromising efficiency
-
BTW, keep in mind that there is no such thing as "universal ref" in C++ standard. It's just a way of thinking about rvalue ref
T&&
in contexts which provide type deduction forT