Конструктор Constexpr не удовлетворяет требованиям, но все же constexpr.Зачем? - PullRequest
0 голосов
/ 05 декабря 2018

Стандарт говорит о шаблонных функциях / конструкторах constexpr в dcl.constexpr / 6 :

Если конкретизированная специализация шаблона шаблона функции constexpr или функции-члена классашаблон не сможет удовлетворить требования к функции constexpr или конструктору constexpr, эта специализация по-прежнему остается функцией constexpr или конструктором constexpr, даже если вызов такой функции не может появляться в константном выражении.Если ни одна из специализаций шаблона не удовлетворяет требованиям для функции constexpr или конструктора constexpr, если она рассматривается как не шаблонная функция или конструктор, шаблон является некорректным, диагностика не требуется.

Интересноечасть:

не удовлетворяет требованиям для конструктора ... constexpr, эта специализация по-прежнему является конструктором ... constexpr

Так что, даже если конструкторпомечен constexpr, его нельзя использовать в константном выражении.

Почему существует это правило?Почему не удаляется constexpr, если функция не удовлетворяет требованиям?

Текущее поведение плохо в двух отношениях:

  • non-constexpr-ness isnне пойман в самом близком местоположении, но в фактическом выражении constexpr, где это используется.Таким образом, мы должны найти нарушающую часть, где constexpr беззвучно удаляется.
  • объект, который предназначен для статической инициализации (поскольку он имеет конструктор constexpr), будет динамически инициализирован без каких-либо ошибок / предупреждений (потому что конструктор не «по-настоящему» constexpr).

Есть ли в этом правиле некоторые плюсы, которые уравновешивают его минусы?

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

В более ранних версиях предложения по изменению языка оно действовало так, как вы предлагаете:

Если бы конкретизированная специализация шаблона шаблона функции constexpr не смоглаудовлетворяют требованиям для функции constexpr, спецификатор constexpr игнорируется, и специализация не является функцией constexpr.

Но позже она была изменена.Мне не удалось отследить какой-либо окончательный ответ на ваш вопрос, но я думаю, что разумно полагать, что ответ состоит в том, что constexpr вносит другие семантические изменения в код, и они сохраняются, даже если функция больше не используется в другихconstexpr заявления.Если вы посмотрите на отчет о дефекте 1358 , в котором содержится изменение к текущей формулировке, вы увидите промежуточную форму слов, включающую примечание о сохранении статуса const независимо от того.

Iтакже подумайте, что хотя сохранение статуса constexpr не является интуитивным, оба ваших аргумента против него неверны:

  1. Поймать constexpr при создании экземпляра шаблона противоречит тому, как C ++шаблоны обычно работают - вы получаете ошибку только при попытке использовать шаблон таким образом, чтобы его нельзя было использовать для этого типа;просто неспособность завершить всю подпись не является ошибкой.Введение механики особых случаев для constexpr было бы излишне запутанным и ограничивало бы полезность, поскольку теперь вам нужно было бы написать разные шаблоны для constexpr способных и не constexpr способных типов.

  2. Поскольку поддерживает спецификатор constexpr, запасной вариант - не общая динамическая инициализация во время выполнения, а динамическая инициализация во время инициализации static s.Это может вызвать проблемы из-за статического порядка инициализации Fiasco, но, по крайней мере, происходит до ввода функции main().

0 голосов
/ 05 декабря 2018

Это правило позволяет вам написать шаблонный конструктор / функцию и пометить его как constexpr, даже если это не всегда constexpr (только по крайней мере иногда).

Например, std::pair имеет constexpr конструкторы , но, конечно, его можно использовать вне константных выражений.

Это очень разумно, потому что в противном случае вам придется дублировать все эти функции (один раз с constexpr и один разбез), даже если код точно такой же.Давайте даже не будем рассматривать двусмысленность.

Поскольку вообще невозможно доказать, что шаблон не может когда-либо удовлетворить constexpr, для него не требуется никакой диагностики (но он плохо сформирован, поэтому компиляторы могут жаловаться вам, если могутдокажите это для данного случая).

Вы правы в том, что это не очень полезно, если вы хотите указать, что «эта функция должна только использоваться в постоянном выражении», но это не то, чтоэта формулировка нацелена на.

Редактировать: Чтобы уточнить, constexpr для функций означает только "допустимо оценивать внутри константного выражения" (более точная формулировка здесь ), not "может оцениваться только во время компиляции" .Напротив, constexpr переменные должны быть инициализированы с помощью константного выражения.


Другое редактирование: у нас есть точная формулировка для обсуждения, благодаря @JackAidley!

Есликонкретизированная шаблонная специализация шаблона функции constexpr не сможет удовлетворить требования для функции constexpr, спецификатор constexpr игнорируется и специализация не является функцией constexpr.

Проблема в том, что«существует по крайней мере один набор аргументов, для которых функция может быть оценена на постоянной основе» - это часть «требований к функции constexpr».Следовательно, компиляторы не могут реализовать это предложение, поскольку невозможно доказать (в общем случае), существует ли такой набор для данной функции (или создания экземпляра шаблона функции).Вы должны либо запутать это требование, либо отказаться от этого аспекта.Похоже, комитет выбрал последнее.

...