Использование производных классов 'typedefs в базе - PullRequest
12 голосов
/ 18 декабря 2010

Я хочу, чтобы производный класс был потомком шаблонного класса. Этот класс зависит от членов потомка. Короче говоря, я хочу, чтобы этот код компилировался:

struct IBootParams
{
    virtual bool GetImmediate() = 0;
};

template <class T>
struct TBootBootParams
{
    typename T::TransType transferType;

    typename T::UseAbort_ useAbort;

    bool GetImmediate()
    {
        if ( transferType == T::e1 )
        {
            return useAbort.someFlag;
        }

        return false;
    }

};

struct BootBootParams : public TBootBootParams<BootBootParams> 
{
    enum SomeEnum
    {
        e1=0,
        e2,
        e3
    };

    struct UseAbort
    {
        bool        someFlag;           

        char        someMember;             
        int         otherMember;        
    } useAbort;

    typedef SomeEnum TransType;
    typedef UseAbort UseAbort_;
};

struct BootAltBootParams : public TBootBootParams<BootAltBootParams> 
{
    enum SomeEnum
    {
        e1=5,
        e2,
        e3
    };

    struct UseAbort
    {
        bool        someFlag;           

        long long       someMember;             
        long long       otherMember;        
    } useAbort;

    typedef SomeEnum TransType;
    typedef UseAbort UseAbort_;
};

int _tmain(int argc, _TCHAR* argv[])
{
    BootBootParams bp;
    BootAltBootParams bpa;

    bool f = bp.GetImmediate();
    f = bpa.GetImmediate();
}

Ответы [ 5 ]

10 голосов
/ 18 декабря 2010

Вы не можете сделать это таким образом.Когда компилятор создает экземпляр TBootBootParams<BootBootParams>, он еще не полностью прочитал полное определение BootBootParams, поэтому вы не можете получить доступ к его элементам из определения TBootBootParams (функции-члены TBootBootParams являются исключением, поскольку они создаются позже).

Обычное решение состоит в том, чтобы иметь класс черт:

template<class T> struct TBootBootParams_traits;

template <class T>
struct TBootBootParams
{
    typename TBootBootParams_traits<T>::TransType transferType;

    typename TBootBootParams_traits<T>::UseAbort_ useAbort;

    bool GetImmediate()
    {
        if ( transferType == TBootBootParams_traits<T>::e1 )
        {
            return useAbort.someFlag;
        }

        return false;
    }

};

struct BootBootParams;
template<> struct TBootBootParams_traits<BootBootParams>
{
    enum SomeEnum
    {
        e1=5,
        e2,
        e3
    };

    struct UseAbort
    {
        bool        someFlag;           

        long long       someMember;             
        long long       otherMember;        
    };

    typedef SomeEnum TransType;
    typedef UseAbort UseAbort_;
};

struct BootBootParams : 
    public TBootBootParams<BootBootParams>, 
    public TBootBootParams_traits<BootBootParams>
{
    UseAbort_ useAbort;
};
4 голосов
/ 18 декабря 2010

Нет способа, которым это может сработать, что не является чем-то вроде взлома. Итак, вот моя попытка взломать:

struct IBootParams
{
    virtual bool GetImmediate() = 0;
};

template <class T>
struct TBootBootParams : public IBootParams
{
    typename T::TransType transferType;

    typename T::UseAbort_ useAbort;

    virtual bool GetImmediate()
    {
        if ( transferType == T::e1 )
        {
            return useAbort.someFlag;
        }

        return false;
    }

};

struct BootBootParams_types
{
    enum SomeEnum
    {
        e1=0,
        e2,
        e3
    };

    struct UseAbort
    {
        bool        someFlag;

        char        someMember;
        int         otherMember;
    } useAbort;

    typedef SomeEnum TransType;
    typedef UseAbort UseAbort_;
};

struct BootBootParams : public BootBootParams_types,
                        public TBootBootParams<BootBootParams_types>
{
};

struct BootAltBootParams_types
{
    enum SomeEnum
    {
        e1=5,
        e2,
        e3
    };

    struct UseAbort
    {
        bool        someFlag;

        long long       someMember;
        long long       otherMember;
    } useAbort;

    typedef SomeEnum TransType;
    typedef UseAbort UseAbort_;
};

struct BootAltBootParams : public BootAltBootParams_types,
                           public TBootBootParams<BootAltBootParams_types>
{
};

int main(int argc, const char * argv[])
{
    BootBootParams bp;
    BootAltBootParams bpa;

    bool f = bp.GetImmediate();
    f = bpa.GetImmediate();
}
2 голосов
/ 18 декабря 2010

Делает ли это то, что вы хотите? Компилируется.

struct IBootParams
{
    virtual bool GetImmediate() = 0;
};

template <class T>
struct TBootBootParams
{
    bool GetImmediate()
    {
        if ( static_cast<T*>(this)->transferType == T::e1 )
        {
            return static_cast<T*>(this)->useAbort.someFlag;
        }

        return false;
    }

};

struct BootBootParams : public TBootBootParams<BootBootParams> 
{
    enum SomeEnum
    {
        e1=0,
        e2,
        e3
    } transferType;

    struct UseAbort
    {
        bool        someFlag;           

        char        someMember;             
        int         otherMember;        
    } useAbort;
};

struct BootAltBootParams : public TBootBootParams<BootAltBootParams> 
{
    enum SomeEnum
    {
        e1=5,
        e2,
        e3
    } transferType;

    struct UseAbort
    {
        bool        someFlag;           

        long long       someMember;             
        long long       otherMember;        
    } useAbort;
};

int main(void)
{
    BootBootParams bp;
    BootAltBootParams bpa;

    bool f = bp.GetImmediate();
    f = bpa.GetImmediate();
}
1 голос
/ 20 декабря 2010

Я попытался немного изменить решение ybungalobill, считая мои собственные потребности. И это то, что я получил

template<class T> 
struct TBootBootParams_traits;

template <class T>
struct TBootBootParams
{
    typedef TBootBootParams_traits<T> Traits;

    typename Traits::TransType transferType;
    typename Traits::UseAbort_ useAbort;

    bool GetImmediate()
    {
        if ( transferType == TBootBootParams_traits<T>::e1 )
        {
            return useAbort.someFlag;
        }

        return false;
    }
};

struct BootBootParams;
struct BootAltBootParams;

template<> 
struct TBootBootParams_traits<BootBootParams>
{
    enum SomeEnum
    {
        e1=5,
        e2,
        e3
    };

    struct UseAbort
    {
        bool        someFlag;           

        long long       someMember;             
        long long       otherMember;        
    };

    typedef SomeEnum TransType;
    typedef UseAbort UseAbort_;
};

template<> 
struct TBootBootParams_traits<BootAltBootParams>
{
    enum SomeEnum
    {
        e1=5,
        e2,
        e3
    };

    struct UseAbort
    {
        bool        someFlag;           

        int someMember;             
        float otherMember;        
    };

    typedef SomeEnum TransType;
    typedef UseAbort UseAbort_;
};

struct BootBootParams : 
    public TBootBootParams<BootBootParams>
{

};

struct BootAltBootParams : 
    public TBootBootParams<BootAltBootParams>
{

};

int main(void)
{
    BootBootParams bp;
    BootAltBootParams bpa;

    bool f = bp.GetImmediate();
    f = bpa.GetImmediate();
}

Подводя итог .. Я использую шаблонный класс как обязательный параметр другого класса для этого класса, размещая там все данные типа. Это как раз то, что мне было нужно. Еще раз спасибо за вариант!

0 голосов
/ 18 декабря 2010

Чтобы этот подход работал, вы должны включить объект класса шаблона в качестве члена родительского класса.

...