Соберем немного конкретики из комментариев.
Отсюда:
Только хотелось бы без специализации, чтобы код не дублировать
Единственным дублированием кода тут будет только заголовок частичной специализации шаблона. В силах писателя определить общий между специализациями код и вынести его в родительский для всех специализаций класс.
А с подобным дублированием справляется шаблон
std::enable_if
[
?]. Часто его используют для выбора поведения шаблона исходя из
черт аргумента шаблона.
В твоем же случае можно успешно применять между реализацией с полем и реализацией без поля.
Например, в виде
такого упрощения определять общее
поведение всего типа.
Отсюда:
соответственно во всех методах, где этот член используется можно будет проверку if constexpr (someCondition)
Я подобные блоки кода называю замусореванием. Это как будто шел человек, захотел есть, пошел к палатке, купил еду, поел, а обертку и все остальное кинул прямо перед палаткой. Намусорил и ушел.
Вот и писатель кода нередко в пылу решения задачи заходит в код, что-то дописывает, решает свои житейские проблемы и в результате код становится замусоренным. В коде больше не видно поведения, в коде появляются всякие сервисные штуки для этого кода. Код становится тяжело читать. А шаблонный код всегда и вдвойне тяжелее читать.
За чистотой кода нужно следить. Подобные вещи, как вот такие блоки
if constexpr
, нужно убирать в функции. А где эти функции лучше расположить? Верно - прямо там, где для их работы определены данные. Поэтому на самом деле
if constexpr
не нужен. Нужно определить набор функций с поведением там где оно возможно. А где нет - определить заглушки чтобы клиентский, относительно вариативного поведения, код не нуждался в проверках и мог просто обращаться к вариативному поведению так, как будто оно не вариативно и есть всегда.
Опять же, тут хорошо подходит пример с
DebugName
[
?], в котором такие заглушки реализованы.