Почему std :: range :: view_interface использует CRTP

Согласно cppreference, шаблон вспомогательного класса для определения представлений view_interface с использованием любопытно повторяющегося шаблоны шаблонов (CRTP).

Какая философия дизайна стоит за ними? Есть ли существенное преимущество перед переопределением метода виртуального базового класса в производном классе?


person 康桓瑋    schedule 08.02.2021    source источник
comment
Вид не владение и легкий вес. Запомни. Наследования нет.   -  person doug    schedule 08.02.2021
comment
@doug: наследование от типа с виртуальными функциями нелегко.   -  person Nicol Bolas    schedule 08.02.2021
comment
@doug single_view<std::function<void()>> является владельцем и не совсем легковесным.   -  person cpplearner    schedule 08.02.2021
comment
@NicolBolas Я должен был быть яснее и сказать «ни то, ни другое».   -  person doug    schedule 08.02.2021


Ответы (1)


Если вы дадите виртуальные функции базового класса, тогда они будут у него. Всегда. Он никогда не может не иметь этих функций, и каждый производный от него класс будет наследовать эти функции.

view_interface имеет функцию empty тогда и только тогда, когда категория диапазона для типа forward_range. То есть empty существует, если begin возвращает прямой итератор, а end возвращает дозор для этого итератора. Но вы можете проверить это только в том случае, если можете запрашивать свойства производного класса. И базовый класс не может этого сделать ... если вы не разрешите ему, указав тип производного класса. Это означает, что это должен быть параметр шаблона, а базовый класс - это шаблон.

И поэтому вы используете CRTP.

Предоставление или отсутствие общих функций на основе категорий итераторов производного класса диапазона - это вся точка класса. Единственная альтернатива - иметь набор базовых классов для каждого типа итератора. Таким образом, у вас будет forward_view_interface для прямых диапазонов, contiguous_view_interface для смежных диапазонов и т. Д. И это было бы болезненно. Но начнется мультипликативный взрыв, потому что некоторые свойства, предоставляемые view_interface, ортогональны категории итератора.

Например, size предоставляется, если диапазон является диапазоном размеров. Но это может произойти для любой категории итераторов, даже для итераторов ввода. Итак, теперь вам нужно sized_forward_view_interface и т. Д.

Или вы можете просто использовать CRTP.

person Nicol Bolas    schedule 08.02.2021