Frage

Ich habe eine Klasse, die dekoriert werden kann mit einer Reihe von add-on-Vorlagen, um zusätzliche Funktionen bereitzustellen.Jedes add-on hat eine Ermittlung addon_value Sie, dass die Basis-Klasse wissen muss.

Der code unten ist ein Beispiel, was ich gerne tun würde.Offensichtlich ist der main () - Funktion nicht kompiliert werden kann.Das Ziel ist für CBase::GetValueOfAddOns (), zu wissen, die den Wert ODER die-ing der addon_value für jedes add-on.Die Berechnung nicht tatsächlich durchgeführt werden, in GetValueOfAddOns(), es muss nur in der Lage sein, um auf das Ergebnis.

template< class T >
class AddOn_A : public T
{
public: 
    AddOn_A( int x ) : T( x ) 
    {};

    enum { addon_value = 0x00000001 };
};

template< class T >
class AddOn_B : public T
{
public: 
    AddOn_B( int x ) : T( x ) 
    {};

    enum { addon_value = 0x00000010 };
};

class CBase
{
public:
    explicit CBase( int x ) : x_( x ) 
    {
        // error LNK2001: unresolved external symbol "public: virtual int __thiscall CBase::GetValueOfAddOns(void)const " (?GetValueOfAddOns@CBase@@UBEHXZ)
        int z = GetValueOfAddOns();
    };

    virtual int GetValueOfAddOns() const = 0;

private:
    int x_;
};

// define an empty AddOn
template< class > class empty 
{
public:
    enum { addon_value = 0x00000000 };
};

// forward declaration and Add-On defaults
template< template< class > class AddOn1 = empty,
          template< class > class AddOn2 = empty,
          template< class > class AddOn3 = empty >
class CMyClass;

// specialized template for the default case
template<> class CMyClass< empty, empty, empty > : public CBase
{
public:
    CMyClass( int x ) : CBase( x ) 
    {};

    enum { addon_value = 0x00000000 };
};

// actual definition
template< template< class > class AddOn1,
          template< class > class AddOn2,
          template< class > class AddOn3 >
class CMyClass : public AddOn1< CBase >,
                 public CMyClass< AddOn2, AddOn3 >
{
public:
    CMyClass( int x ) : AddOn1< CBase >( x ),
                        CMyClass< AddOn2, AddOn3 >( x )
    {};

    enum { addon_value = AddOn1< CBase >::addon_value | CMyClass< AddOn2, AddOn3 >::addon_value };

    int GetValueOfAddOns() const
    {
        return addon_value;
    }
};

int _tmain( int argc, _TCHAR* argv[] )
{
    CMyClass< AddOn_A > A( 0 );
    _ASSERT( A.GetValueOfAddOns() == AddOn_A< CBase >::addon_value );

    CMyClass< AddOn_A, AddOn_B > AB( 0 );
    _ASSERT( AB.GetValueOfAddOns() == ( AddOn_A< CBase >::addon_value | AddOn_B< CBase >::addon_value ) );

    return 0;
}

Vielen Dank für jede Hilfe, PaulH

War es hilfreich?

Lösung

Nicht sicher, dies ist die eleganteste Art und Weise, aber die folgenden ist recht einfach:

Fügen Sie diese auf CMyClass:

enum {AddonsValues = AddOn1<CBase>::addon_value | CMyClass<AddOn2, AddOn3>::AddonsValues};

int GetValueOfAddOns()
{
    // return the result of OR-ing the addon_value of each add-on.
    return AddonsValues;
};

und dies das Fach CMyClass<empty, empty, empty>:

enum {AddonsValues = 0};

Andere Tipps

Wenn Sie diese Funktion reinen virtual machen, können Sie es in CMyClass implementieren, wo Sie alle Informationen zur Verfügung haben. Ändern Sie einfach Ihre empty Klasse enum { addon_value = 0x00000000 }; zu definieren, was diese leichter machen wird.

Lassen Sie uns machen es besser:

Finden Sie Ihre neue Frage das problem mit der Hierarchie hier Ich habe das gelöst AddOnValues problem gab es auch, und es gibt keine Notwendigkeit für template-meta-Programmierung, wirklich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top