C ++: с CRTP класс, определенный в производном классе, недоступен в базовом классе - PullRequest
7 голосов
/ 04 апреля 2011

Вот (упрощенный) базовый класс:

template <class T>
class SharedObject
{
protected:
    QExplicitlySharedDataPointer <typename T::Data> d;
};

А вот и производное:

class ThisWontCompile : public SharedObject <ThisWontCompile>
{
private:
    friend class SharedObject;
    struct Data : public QSharedData
    {
        int id;
    };
};

Есть ли обходной путь для доступа к ThisWontCompile :: Data из SharedObject ? Что именно можно и что нельзя делать с производным объектом от базового объекта?

1 Ответ

13 голосов
/ 04 апреля 2011

Это на самом деле не связано с доступностью и дружбой, это связано с использованием CRTP. Рассмотрим следующий пример, который также демонстрирует проблему:

template <class T>
struct Base
{
    typedef typename T::Data Data;
};

struct ThisWontCompile : public Base<ThisWontCompile>
{
    struct Data { };
};

Проблема в том, что ThisWontCompile является неполным в то время, когда оно используется в качестве аргумента шаблона для Base, поэтому его можно использовать только как неполный тип в Base.

Чтобы найти несколько решений вашей конкретной проблемы, обратитесь к ответам на этот другой вопрос , особенно к рекомендации Мартина использовать класс черт, который в основном будет выглядеть так:

// Base
template <typename T>
struct BaseTraits;

template <typename T>
struct Base
{
    typedef typename BaseTraits<T>::Data Data;
};

// Derived
struct Derived;

template <>
struct BaseTraits<Derived>
{
    struct Data { };
};

struct Derived : public Base<Derived>
{
};

typename BaseTraits<Derived>::Data может использоваться как в Derived, так и в Base. Если Derived сам является шаблоном, вы можете использовать частичную специализацию для класса черт.

...