I'm making a move-only equivalent of std::function
. move_function
contains a pointer to a base class, move_function_base
which type erases the underlying functor type. move_function_imp
inherits from move_function_base
and holds the typed underlying functor. move_function_imp
is defined like so:
template<class F, class ReturnType, class... ParamTypes>
class move_function_imp : public move_function_base<ReturnType, ParamTypes...> {
typename std::remove_reference<F>::type f_;
public:
virtual ReturnType callFunc(ParamTypes&&... p) override {
return f_(std::forward<ParamTypes>(p)...);
}
explicit move_function_imp(const F& f) : f_(f) {}
explicit move_function_imp(F&& f) : f_(std::move(f)) {}
move_function_imp() = delete;
move_function_imp(const move_function_imp&) = delete;
move_function_imp& operator=(const move_function_imp&) = delete;
};
When I use this I get an error that the constructors cannot overload each other. What am I doing wrong? The full code is located here.
edit: error pasted from ideone link:
prog.cpp: In instantiation of ‘class move_function_imp<main()::__lambda0&, void>’:
prog.cpp:39:30: required from ‘move_function<ReturnType(ParamTypes ...)>::move_function(F&&) [with F = main()::__lambda0&; ReturnType = void; ParamTypes = {}]’
prog.cpp:62:38: required from here
prog.cpp:20:12: error: ‘move_function_imp<F, ReturnType, ParamTypes>::move_function_imp(F&&) [with F = main()::__lambda0&; ReturnType = void; ParamTypes = {}]’ cannot be overloaded
explicit move_function_imp(F&& f) : f_(std::move(f)) {}
^
prog.cpp:19:12: error: with ‘move_function_imp<F, ReturnType, ParamTypes>::move_function_imp(const F&) [with F = main()::__lambda0&; ReturnType = void; ParamTypes = {}]’
explicit move_function_imp(const F& f) : f_(f) {}
^
prog.cpp:19:12: error: ‘move_function_imp<F, ReturnType, ParamTypes>::move_function_imp(const F&) [with F = main()::__lambda0&; ReturnType = void; ParamTypes = {}]’, declared using local type ‘main()::__lambda0’, is used but never defined [-fpermissive]
It took a little toying around but I got this
Snippet for answer completeness.
template <class>
struct remove_reference_except_function {};
template <class R, class... Args>
struct remove_reference_except_function<R(&)(Args...)>
{
typedef R(&type)(Args...);
};
template <class R, class... Args>
struct remove_reference_except_function<R(&)(Args......)> //varardic function
{
typedef R(&type)(Args......);
};
//I dont think you can have an rvalue reference to a function? Or can you dereference a non-capturing lambda?
template <class T>
struct remove_reference_except_function<T &>
{
typedef T type;
};
template <class T>
struct remove_reference_except_function<T &&>
{
typedef T type;
};
template< class ReturnType, class... ParamTypes>
struct move_function_base{
virtual ReturnType callFunc(ParamTypes... p) = 0;
};
template<class F, class ReturnType, class... ParamTypes>
class move_function_imp : public move_function_base<ReturnType, ParamTypes...> {
//Using std::remove_reference on a normal function gives you an invalid type for declaring a variable. Hence the custom reference removal
typename remove_reference_except_function<F>::type f_;
public:
virtual ReturnType callFunc(ParamTypes... p) override {
return f_(std::forward<ParamTypes>(p)...);
}
explicit move_function_imp(const typename std::remove_reference<F>::type& f) : f_(f) {}
explicit move_function_imp(typename std::remove_reference<F>::type&& f) : f_(std::move(f)) {}
move_function_imp() = delete;
move_function_imp(const move_function_imp&) = delete;
move_function_imp& operator=(const move_function_imp&) = delete;
};
As people pointed out your main issue was the template parameters collapsing to the same type giving you the overload error, so I used the normal std::remove_reference to remedy that.
Also you had a rogue rvalue reference in the callFunc of move_function_imp.
I had to create a custom remove_reference for declaring f_ because if you removed the reference from a normally created function (ff in my example) you got a compile error.
Honestly I'm a little bug-eyed from working on it should anyone have corrections I'd be happy to hear them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With