Поможет ли концепция облегчить необходимость CRTP для достижения статического полиморфизма?

Так как я обнаружил CRTP несколько лет назад я использовал его во многих местах для достижения полиморфизма во время компиляции для очень интенсивных вычислительно-ориентированных кодов. Замечательно «впрыскивать» функции-члены в классы универсальным способом, когда нужно заботиться как об универсальности, так и о максимальной производительности во время выполнения.

Я прочитал / посмотрел несколько вещей на concepts lite которая будет (я надеюсь) частью следующего C++ стандарт. Будет совершенно удивительно проектировать функции в более абстрактной и обобщенной манере, избегая ужасных линий SFINAE/std::enable_if Я сейчас пользуюсь.

Я не проверял g++ ветви, которые реализуют концепции, чтобы поиграть с ними и исследовать методы метапрограммирования, которые мне нравятся по-новому. Но, возможно, некоторые из вас имеют. Сначала я подумал, что концепции не решат проблему статического полиморфизма, но так как подобные вещи могут сильно зависеть от уловок, я могу ошибаться. Итак, мой вопрос заключается в следующем: Смогут ли концепты Lite достичь полиморфизма во время компиляции (как мы можем сделать через CRTP) более удобным способом? (примеры кода приветствуются).

4

Решение

Я не должен так думать. Concepts Lite заменит ваше использование enable_if, но я не уверен, что это учитывает новые методы для CRTP. С другой стороны, могут быть некоторые интересные вещи, которые можно сделать.

Я скажу, что столкнулся с некоторыми проблемами CRTP при более ранней реализации концепций lite. Проверка ограничений требует, чтобы аргументы типа были полные типы. Если у вас есть базовый класс, параметризованный над производным классом, вам нужно отложить проверку до точки использования. Например:

template<Fooable D>
struct crtp {
void f() {
static_cast<D*>(this)->g();
}
};

struct derived : crtp<derived> { // Error!
};

Когда вы пытаетесь проверить Fooable<derived>, производное еще не определено. Лучше написать так:

template<typename D>
struct crtp {
void f() requires Fooable<D>() {
static_cast<D*>(this)->g();
}
};

Сейчас, Fooable<D>() проверяется только когда f() называется.

Просто к вашему сведению.

6

Другие решения

Поэтому мой вопрос заключается в следующем: смогут ли понятия облегчить полиморфизм во время компиляции (как мы в настоящее время можем сделать с помощью CRTP) более удобным способом? (примеры кода приветствуются).

Нет — они не будут подавлять CRTP в общем. Понятия lite в основном касаются простоты перегрузки и определения универсальных функций, а также простоты синтаксических проверок:

template<typename T>
concept bool EqualityComparable()
{
return requires(T a, T b)
{
bool = {a == b};
bool = {a != b};
};
}

template<InputIterator I, EqualityComparable T>
I find(I first, I last, T x);
// or
template<InputIterator I>
I find(I first, I last, EqualityComparable x);

Я думаю, что концепции Lite будет подавлять многие случаи использования std::enable_if,

CRTP имеет разные варианты использования, некоторые из них действительно связаны с перегрузкой, например:

template<typename Derived>
void do_something(const CRTP_Base<Derived> &x);

Но CRTP не ограничивается перегрузкой, у него есть другие приложения: например, основной вариант использования для std::enable_shared_from_this не подразумевает никакой перегрузки:

class Widget : std::enable_shared_from_this<Widget>
{
// ...
};

Некоторые из случаев использования CRTP задействовать даже виртуальные функции — например, автоматическую реализацию Cloneable интерфейс:

// Simple example, no covariance, etc
struct Base
{
typedef unique_ptr<Base> Unique;

virtual Unique clone() const = 0;
virtual ~Base() = default;
};

template<typename Derived>
struct ImplementCloneable: protected Base
{
Unique clone() const override
{
return Unique(new Derived(static_cast<const Derived&>(*this)));
}
protected:
~ImplementCloneable() = default;
};

struct Widget: ImplementCloneable<Widget>
{
};
5

Насколько я понимаю, должна быть возможность использовать Concepts Lite для определения своего рода «статического интерфейса», который говорит о том, что Концепция требует, чтобы определенные функции-члены существовали в классе и могли вызываться с помощью определенных сигнатур. Похоже, что это может быть полезно для статического полиморфизма в некоторых ситуациях.

Однако я не думаю, что это действительно предполагаемое использование для Concepts Lite. В выступлениях, которые я видел, кажется, предположили, что должно быть относительно немного Концепций, и они должны быть довольно фундаментальными (думает как концепция «прямого итератора»), а не использоваться для определения специальных статических интерфейсов.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector