Использование CRTP, производное «using» в C ++ 20 - PullRequest
0 голосов
/ 22 января 2019

Я пытаюсь сосредоточиться на CRTP и C ++ 20.По сути, я хотел бы иметь статическое наследование, которое может получить доступ к производным типам typedef s и using:

template <typename Derived>
class inherit
{
public:

    Derived& underlying()
    {
        return static_cast<Derived&>(*this);
    }

    Derived const& underlying() const
    {
        return static_cast<Derived const&>(*this);
    }
};

template <typename Derived>
class tester : public inherit<Derived>
{
public:
    using value_type = typename Derived::value_type;
};

class real : public tester<real>
{
public:
    using value_type = int;
};


int main()
{
    return 0;
}

Это, как объяснено в некоторых других вопросы по SO не разрешены в C ++ 14 (ответы, которые я нахожу, относятся к этому стандарту и к C ++ 11).Насколько я понимаю, в C ++ 17 тоже нет пути (если мой компилятор прав).

Каков текущий статус C ++ 20?Есть ли лучшие решения с готовым стандартом?

1 Ответ

0 голосов
/ 22 января 2019

Нет, это все еще не разрешено в C ++ 20. И это, несомненно, останется недопустимым в C ++ до тех пор, пока производный класс будет неполным, пока не будет завершен процесс создания шаблона базового класса. Что, несомненно, останется таким, как есть, потому что то, что вам нужно, потребует, чтобы компилятор до некоторой степени скомпилировал производный класс, прежде чем создавать экземпляр шаблона базового класса, и эта степень «забегая вперед» просто не практична. И может привести к бесконечным циклам или другим запутанным конструкциям, поскольку ожидается, что объявления / определения членов производного класса будут иметь доступ к доступным объявлениям базового класса.

Рассмотрим простой случай некоторых требований итераторов. Итераторы должны иметь value_type (на данный момент игнорировать весь бизнес "iterator_traits"; наша цель - использовать черты по умолчанию), которые будет предоставлять производный класс. Наш вспомогательный итератор CRTP базовый класс будет полезно использовать объявление производного класса value_type для генерации pointer, reference и так далее. Но operator* производного класса должен иметь возможность возвращать reference, который унаследован от базового класса, который сам зависит от компиляции объявления value_type в производном классе. Итак ... что компилируется первым: создание шаблона базового класса или производный класс? Это должен быть один или другой; это не может быть и то и другое одновременно.

Конечная проблема в том, что CRTP просто не то, что мы действительно хотим. То, что мы действительно хотим, - это иметь возможность хранить последовательность объявлений / определений в централизованном месте, а затем внедрять их в класс по мере необходимости. IE: настоящий миксин. Использование наследования типа шаблона с именами производного класса - это просто самый близкий инструмент, который язык C ++ должен достичь. Но поскольку наследование и создание шаблона никогда не предназначались для удовлетворения этой потребности, естественно, с ним будут связаны бородавки.

Таким образом, вам по-прежнему придется полагаться на типичную альтернативу: использование класса «черты», основанного на типе производного класса.

...