2017-02-17 18 views
0

Это мой attempt:Где я ошибаюсь?

#include <iostream> 
#include <functional> 

class Voice; 

class EnvelopeMultiPoints 
{ 
public: 
    std::function<double(Voice &, double)> mCallback; 

    void SetupModulation(std::function<double(Voice &, double)> callback, int paramID) { 
     mCallback = callback; 
    } 
}; 

class Voice 
{ 
public: 
    EnvelopeMultiPoints mEnvelopeMultiPoints; 
}; 

class VoiceManager 
{ 
public: 
    Voice mVoices[16]; 

    inline void UpdateVoices(std::function<void(Voice &)> callback) { 
     for (int i = 0; i < 16; i++) { 
      callback(mVoices[i]); 
     } 
    } 
    static void SetupEnvelopeMultiPointsModulation(Voice &voice, std::function<double(Voice &, double)> callback, int paramID) { 
     voice.mEnvelopeMultiPoints.SetupModulation(callback, paramID); 
    } 
}; 

class Oscillator 
{ 
public: 
    double ModulatePitch(Voice &voice, double currentValue) { 
     // somethings with voice 
     return currentValue * 10.0; 
    } 
}; 

int main() 
{  
    VoiceManager voiceManager; 
    Oscillator *pOscillator = new Oscillator(); 

    int param = 100; 
    auto callback = std::bind(&Oscillator::ModulatePitch, pOscillator, std::placeholders::_1, std::placeholders::_2); 
    voiceManager.UpdateVoices(std::bind(&VoiceManager::SetupEnvelopeMultiPointsModulation, std::placeholders::_1, callback, param));  

    Voice voice = voiceManager.mVoices[0]; 
    std::cout << voice.mEnvelopeMultiPoints.mCallback(voice, 1.0) << std::endl; 

    delete pOscillator; 
} 

создать своего рода Voice Updater «основной» итератора, который я могу передать какой-либо функции позже. Он выполняет итерацию всех голосов и передает функцию, которая мне нужна для этой итерации.

Но кажется, что я ошибаюсь, чтобы связать функцию Oscillator::ModulatePitch, чтобы перейти к Updater?

Где я здесь не так?

+1

Вы можете использовать лямбды? Использование 'auto callback = [pOscillator] (авто и голос, double d) {return pOscillator-> ModulatePitch (голос, d); }; 'работает для меня. Общее правило заключается в том, чтобы избежать «std :: bind», когда вы можете использовать lambdas. – Maikel

+1

Рассматривали ли вы замену 'std :: bind' на lambdas? – nwp

+1

, используя явный тип для 'callback', исправит его. 'std :: function callback = ...' Но я не могу точно объяснить, почему :) – pergy

ответ

0

Как pergy написал в своем комментарии, если вы используете std::function<double(Voice &, double)> callback = ... вместо auto, он работает. Причина в том, что он заставляет преобразование из объекта bind в std::function.

Если вы

auto callback1 = std::bind(&Oscillator::ModulatePitch, pOscillator, std::placeholders::_1, std::placeholders::_2); 
std::function<double(Voice &, double)>callback2 = std::bind(&Oscillator::ModulatePitch, pOscillator, std::placeholders::_1, std::placeholders::_2); 
std::cout << typeid(callback1).name(); 
std::cout << typeid(callback2).name(); 

вы увидите, что возвращающиеся типы Дифференц. И в этом случае второй bind пытается построить свой объект с использованием второго типа (который не работает). Я думаю, что есть проблема с оператором преобразования (от bind to std :: function), который не вызывается внешним связыванием.