2013-08-25 10 views
5

Sto facendo un equivalente di solo spostamento di std::function. move_function contiene un puntatore a una classe base, move_function_base, che tipo cancella il tipo di functor sottostante. move_function_imp eredita da move_function_base e contiene il functor sottostante digitato. move_function_imp è definito in questo modo:Impossibile eseguire il overload del costruttore in C++

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

Quando uso questo io ottenere un errore che i costruttori non possono sovraccaricare l'un l'altro. Che cosa sto facendo di sbagliato? Il codice completo si trova here.


edit: errore di collegamento incollato da Ideone:

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] 
+4

Se 'F' è' T & '(un riferimento), il primo ctor sarà' (T & const &) 'che collassa a' (T &) 'e il secondo sarà' (T & &&) 'che collassa a '(T &)' pure. Anche qui hai bisogno di 'remove_reference'. – Xeo

+1

SE 'F' è un tipo di funzione, si chiederebbe un riferimento alla funzione rvalue, come' R (&&) (T1, T2) '. Non penso che un tale tipo esista. –

+2

Inoltre, usare 'ParamTypes &&' per' callFunc' è una pessima idea - se si specifica '', ad esempio, 'callFunc' sarà' void callFunc (int && p) ', quindi accetta solo argomenti rvalue. Usa semplicemente 'ParamTypes' senza ulteriori modifiche (puoi mantenere' std :: forward'ing per spostare gli argomenti di valore-by). – Xeo

risposta

1

C'è voluto un po 'toying intorno ma ho ottenuto this

Snippet per risposta completezza.

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

Dato che le persone hanno sottolineato il problema principale era i parametri del modello che crollano per lo stesso tipo dandovi l'errore di sovraccarico, quindi ho usato il normale std :: Remove_Reference per porre rimedio a questo.

Inoltre, nel callFunc di move_function_imp è presente un riferimento rogue.

Ho dovuto creare un parametro remove_reference personalizzato per la dichiarazione di f_ perché se si rimuove il riferimento da una funzione normalmente creata (nel mio esempio) si ottiene un errore di compilazione.

Onestamente sono un po 'coccolato dal lavorarci su, se qualcuno avesse delle correzioni sarei felice di sentirle.

Problemi correlati