[ glorius @ 27.09.2013. 14:00 ] @
Pokusavam da napravim klasu koja koristi policy based dizajn pomocu templates. 'Host' klasa je AnimationController koja koristi policies za advance animacije. Drugim recima, u policy klase smestam logiku za increment current frejma animacije dok AnimationController vodi evidenciju o ellapsed time, duration itd.

Evo dela trenutnog koda:

Code:


template <typename T>
class LinearAdvancePolicy
{
public:
    static bool advance(T& currentValue, const T& start, const T& end, float duration,
        float elapsedTime)
    {
        float pos = elapsedTime / duration;
        currentValue = (T)(start + (end - start)*pos);
        return currentValue >= end;
    }
};
 
template <typename ValueType,
          template <typename> class AdvancePolicy = LinearAdvancePolicy >
class AnimationController
{
.....
       void update(float dt)
       {
               bool bIsFinished = AdvancePolicy<ValueType>::advance(...);
               ....
       }
};



Kapiram beneficije koriscenja template template parameters.
Ono sto ne razumem je kako da napisem template za AnimationController ako u policy klasu dodam jos jedan template parametar:

Code:


// namera je da u policy dodam parametar koji odredjuje da li je animacija reversed
template <typename T, bool bReversed>
class LinearAdvancePolicy { ... }



Kako sada prilagoditi template parametre za AnimationController?

U smislu:

Code:


template <typename ValueType,
          template <typename, bool> class AdvancePolicy = LinearAdvancePolicy >
class AnimationController {...}



ali to ne radi...

Takodje, sta bi se desilo da to radi, onda bih instanciranje objekta morao da napisem ovako:

AnimationController<int, LinearAdvancePolicy<int, true> > m_animController;

Ovim koriscenje template template parameters gubi smisao posto explicitno navodim da je prvi parametar za LinearAdvancePolicy int....

Mozda je ovo i nemoguce implementirati ili mogu promeniti dizajn (da stavim bReversed u AnimationController) ali je glavno pitanje kako 'ubaciti' vise parametara u policy klasu kada host klasa ocekuje da policy primi preko template template parametra?





[ Goran Arandjelovic @ 28.09.2013. 22:42 ] @
Hm, ima dosta rešenja tog problema, e sada, zavisi i koji kompajler koristiš trenutno? Ako je GCC, koji GCC? Ako je VC++, koji VC++? Tj, da li imaš variadic i alias templejte, itd.
Pada mi na pamet i C++98 rešenje, ali hajde da ne pišem ništa...možda imaš bolji kompajler pa bi to moglo i lakše.

I još jedno pitanje: Kako bi iskoristio taj parametar bReversed? Ako ga ne bi procesirao statički, onda nema puno smisla da ga koristiš kao templejt parametar.

[Ovu poruku je menjao Goran Arandjelovic dana 29.09.2013. u 00:11 GMT+1]
[ glorius @ 29.09.2013. 06:11 ] @
Hehe, mozda imam bolji kompajler...
U pravu si za bReversed, trebalo bi to staviti u AnimationController pa da se preda policy klasi kao parametar.

[Ovu poruku je menjao glorius dana 29.09.2013. u 07:22 GMT+1]
[ Goran Arandjelovic @ 29.09.2013. 12:19 ] @
Nisam to mislio, nego sledeće:

Code:

template<bool b>
struct X
{
  static void F()
  {
    if(b)
    {
    ...
    }
  }
};


Ako na ovaj način koristiš b u runtime-u onda on ne treba da bude templejt parametar. Smisleno je jedino ako radiš neku parcijalnu specijalizaciju po njemu.
Takođe, možda je loše da taj bool bude parametar AnimationController klase. Šta ako imaš neki parametar koji je specifičan samo za neku određenu polisu?
[ glorius @ 29.09.2013. 16:06 ] @
Malo sam prelistao knjigu C++ Templates: The Complete Guide i (ako imate tu knjigu pri ruci) "15.1.6 Member Templates versus Template Template Parameters" mi je dao odgovor na pitanje.

Evo novog dizajna:

Code:


template <bool bReversed>
class LinearAdvancePolicy
{
public:
    template<typename T>
    static bool advance(T& currentValue, const T& start, const T& end, float duration,
        float elapsedTime)
    {
        float pos = elapsedTime / duration;

        if(!bReversed)
        {
            currentValue = (T)(start + (end - start)*pos);
            return currentValue >= end;
        }
        else
        {
            currentValue = (T)(end - (end - start)*pos);
            return currentValue <= start;
        }    
    }
};

template <typename ValueType,
          typename AdvancePolicy = LinearAdvancePolicy >
class AnimationController :
    public GameObject
{
public:
    enum Properties
    {
        CurrentValue
    };

    enum Notifications
    {
        CurrentValueChanged, 
        AnimationFinished
    };

    AnimationController(ValueType start, ValueType end, float duration, bool bReversed = false)
        : m_currentValue(this, CurrentValue)
        , m_start(start)
        , m_end(end)
        , m_fDuration(duration)
        , m_bReversed(bReversed)
    {
        reset();
    }

    ~AnimationController(void)
    {}

    void update(float dt)
    {    
        if(m_bFinished)
        {
            return;
        }

        m_fElapsedTime += dt;
        // temporary value because advance need real type of ValueType and not Property<ValueType>
        ValueType value = m_currentValue;
        bool bFinished = AdvancePolicy<m_bReversed>::advance<ValueType>(value, m_start, m_end, m_fDuration, m_fElapsedTime);
        m_currentValue = value;

        if(bFinished)
        {
            m_bFinished = true;
            notify(AnimationFinished);
        }
    }

    void reset()
    {
        m_currentValue = m_start;
        m_fElapsedTime = 0.0f;
        m_bFinished = false;
    }

    const ValueType& currentValue() const
    {
        return m_currentValue.value();
    }

    void setReversed(bool bReversed)
    {
        m_bReversed = bReversed;
    }

private:
    float m_fDuration;
    float m_fElapsedTime;
    ValueType m_start;
    ValueType m_end;
    Property<ValueType> m_currentValue;
    bool m_bFinished;
    bool m_bReversed;
};

....

AnimationController<int, LinearAdvancePolicy<true> > ac(0, 10, 2);



U sustini, bReversed mogu predati kao argument funkcije a ne preko template ali sam zeleo da vidim kako mogu da konfigurisem policy preko template parametra.
Ovakav dizajn i nije preterano koristan, bool bReversed moze da ide i preko parametara funkcije a ne preko template parametra posto ce mozda doci do potrebe da dinamicki reversujem animaciju (povlacenje poluge npr. koja se posle vraca) i to cu izmeniti.

Inace, sad mi ovo dozvoljava da specijalizujem Policy klasu.

Citat:
Takođe, možda je loše da taj bool bude parametar AnimationController klase.

Trebao bi zbog mogucnosti menjanja u runtime.

Citat:
Šta ako imaš neki parametar koji je specifičan samo za neku određenu polisu?

Ovo je bas dobro pitanje. Sa ovakvim dizajnom to mozda i nije moguce, osim da obezbedim policy za policy, tj. da template parametar policy klase bude opet neka klasa koja ce dodati parametre i mozda cak funkcionalnost ali to vec komplikuje stvari.


(Malo pre sam opet pogledao kod i uvideo da ima anomalija - bReversed se inicijalizuje sa true u LinearAdvancePolicy pa se posle u update setuje sa m_bReversed ali neka stoji tako za sad u ovom primeru cisto radi diskusije)

[Ovu poruku je menjao glorius dana 29.09.2013. u 18:11 GMT+1]