2017-01-30 14 views
4

У меня есть рабочая виртуальная функция add, которая использует следующие настройки:как передать VARIADIC Params к виртуальной функции

using Func = std::function<std::vector<unsigned char>()>;  

class cfExecutor { 
public: 
    cfExecutor(); 
    virtual ~cfExecutor(); 
    /// Enqueue a function to be executed by this executor. This and all      
    /// variants must be threadsafe. 
    virtual void add(Func) = 0;        
    virtual void add(std::vector<Variant> params, Func callback) = 0; 
}; 


class ManualExecutor : public cfExecutor                    
{                             

    std::mutex lock_;    // avoid multiple entity updating the function container       
    std::queue<Func> funcs_;  // functions queued for running             

    public:                           
    std::map<int8_t, Func> funcs; // Function container (priority,Func) - added functions to this Executors  

    ManualExecutor() {}                        
    ManualExecutor(ManualExecutor&& other):                   
        funcs(std::move(other.funcs))                 
    {}                            
    ~ManualExecutor() {}                        

    void add(Func callback);                   
    void add(std::vector<Variant> params, Func callback);      
};                             

Затем я хотел добавить VARIADIC Params функции - как это:

using Func = std::function<std::vector<unsigned char>(const auto&...args)>; 

Однако я получаю неявную ошибку [неявные шаблоны могут быть не «виртуальными»]

Как определить функцию добавления с помощью переменных параметров?

до сих пор я решил, что с помощью следующих действий:

using Func = std::function<std::vector<unsigned char>(std::vector<Variant>)>; 

, а затем с функцией лямбда обрабатывать принимающие арг внутри вектора - что-то вроде этого:

auto lambdaFunction = [](std::vector<Variant> vec){   

    std::vector<unsigned char> result;      
    cout << "- Hello from executor - lambdaFunction ";  
    std::cout << ": parameters : ";       
    for(auto a: vec) {          
     std::cout << a << ",";        
    }              
    std::cout << std::endl;         

    std::string s("this is the result");     
    result.insert(result.end(),s.begin(), s.end());   
    return result;           
};   
+1

При использовании 'авто ...' 'то Func' не конкретный тип. Вам нужно сделать его псевдонимом шаблона, например: 'template с помощью Func = std :: function ;' – Nawaz

+3

Вы хотите добавить функции с разными сигнатурами к тому же cfExecuror, или функции с той же вариационной сигнатурой или что-то еще? –

+0

разных подписей было бы неплохо, однако sofar Я просто хочу иметь функции, которые принимают variadic params – serup

ответ

2

Похоже, что вы хотите передать связанную функцию.

Это можно сделать с помощью std::bind. Вам не нужно менять add в любом случае или добавить перегруженность vector<variant>. Просто назовите его следующим образом:

std::vector<unsigned char> myfunction (int, const char*, Foo&); 

... 
int i = 123; 
const char* s = "abc"; 
Foo foo{1,2,3}; 
executor->add(std::bind(myfunction, i, s, foo)); 

Используйте его с регулярными функциями, функции-члены, функции типа объектов («функторы») или лямбды. С inline lambdas это не имеет особого смысла, поскольку вы можете захватывать данные в самой лямбда.

executor->add([&i,s,&foo](){ ... use(i); use(s); use(foo); } 

На самом деле вы всегда можете заменить выражение bind с lambda, который может мне более читаемым. Сравните:

int foo; 
std::bind(std::operator<<, std::cout, foo); 

против

[foo]() { return std::cout << foo; } 
+0

Это то, что я искал - я постараюсь адаптировать свой код соответственно - спасибо – serup

2

AFAIK, вы не можете использование 'auto' в функции прототип еще.

Вы, вероятно, хотите сделать, как следующее:

template<typename ... Args > 
using Func =std::function<std::vector<unsigned char>(const Args&...args)>; 

template<typename ... Args > 
class cfExecutor {       
public: 
    cfExecutor();       
    virtual ~cfExecutor(); 
    virtual void add(Func<Args...>) = 0; 

    }; 
+0

Обратите внимание, что 'args' не требуется в псевдониме шаблона. – Nawaz

+0

У меня проблема с использованием этого принципа в классе, который имеет этот cfExecutor как родительский – serup

+0

Я получаю недопустимое использование имени шаблона - не совсем уверен, что происходит с этой настройкой, возможно, я не очень понимаю ваше решение - я добавил больше info на мой вопрос, не могли бы вы снова взглянуть – serup

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

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