2016-03-18 6 views
0

Я хочу, чтобы усовершенствовать форвардный аргумент производному классу через базовый класс. Единственная идея, которую я имею, - реализовать не виртуальную совершенную функцию пересылки в базовом классе и перегружать виртуальные функции для lvalues и rvalues. Что-то вроде этого:безупречная пересылка по базовому классу

Рассмотрим:

#include <iostream> 
#include <memory> 
#include <string> 

class base_t 
{ 
public: 
    virtual ~base_t() = default; 

    template<typename T> 
    void perfect_forward(T&& value) 
    { 
     process(std::forward<T>(value)); 
    } 

protected: 
    virtual void process(const std::string& value) = 0; 
    virtual void process(std::string&& value) = 0; 
}; 

class derived_t : public base_t 
{ 
protected: 
    void process(const std::string& value) override final 
    { 
     std::cout << "derived_t::process(const lvalue&)" << std::endl; 
    } 

    void process(std::string&& value) override final 
    { 
     std::cout << "derived_t::process(rvalue&&)" << std::endl; 
    } 
}; 

int main(int argc, const char* argv[]) 
{ 
    const std::string lvalue; 
    auto rvalue = []() { return std::string(); }; 

    std::unique_ptr<base_t> base(new derived_t); 
    base->perfect_forward(lvalue); 
    base->perfect_forward(rvalue()); 
} 

Но это имеет мало смысла, потому что вместо шаблона perfect_forward функции в базовом классе я могу просто предоставить две перегрузки для виртуального process. Как я могу избежать дублирования кода в производном классе для метода process и использовать его std::forward через интерфейс base_t?

+0

Если вам нужен динамический полиморфизм, вам понадобится виртуальный вызов в какой-то момент, и функциональные шаблоны не могут быть виртуальными, конечно. Вы можете иметь шаблонную функцию в 'производном_t', которая может быть вызвана из обеих перегрузок в производном классе. – Pixelchemist

+0

Кажется, что предоставление двух перегрузок для виртуальной функции в базовом классе является самым простым способом :( – user1641854

+0

Вы можете просто использовать 'virtual void process (std :: string value)'. – Simple

ответ

3

Если вы не хотите взять std::string по значению, есть подход с использованием класса подмешать, но это требует изменений вашего класса: иерархия

template<class D> 
class process_mixin : public base_t { 
protected: 
    void process(std::string const& value) override final { 
     return ((D*)this)->do_process(value); 
    } 

    void process(std::string&& value) override final { 
     return ((D*)this)->do_process(std::move(value)); 
    } 
}; 

class derived_t : public process_mixin<derived_t> { 
protected: 
    template<typename T> 
    void do_process(T&& value) { 
    } 

    friend process_mixin<derived_t>; 
}; 

process_mixin имеет только записать один раз. С этого момента все, что происходит от base_t, может вместо этого выводиться из process_mixin, и вы получаете идеальный интерфейс пересылки.

 Смежные вопросы

  • Нет связанных вопросов^_^