Исключения в шаблонных нетиповых аргументах
Стандарт C++17 гласит:
Шаблонный аргумент для нетипового шаблонного параметра должен быть преобразованным константным выражением...
в то время как
значение константного выражения не должно быть адресом
- строковый литерал
- подобъект
- некоторые другие исключения...
Насколько я понимаю, логическое обоснование исключения строковых литералов заключается в том, что в зависимости от реализации могут возникнуть A<"abc">
в разных единицах перевода могут возникать разные экземпляры (так как строковые литералы имеют внутреннюю связь), или может быть так, что адреса строковых литералов определяются во время связывания (поскольку строковые литералы хранятся в некоторой специальной постоянной памяти).
Первый вопрос: верно ли мое понимание обоснования исключения строковых литералов?
И второй вопрос: в чем причина исключения подобъектов объектов со статической продолжительностью хранения? Я подозревал, что проблема может быть в выравнивании, но выравнивание выполняется во время компиляции, верно?
1 ответ
Основная идея состоит в том, что искаженное имя будет включать в себя (имя) символ, адрес которого берется. Для строкового литерала такого символа нет, поэтому вам придется включать сам литерал. Возможность указания подобъектов также потребует, чтобы в календари входили (возможно, несколько) неоднозначные имена типов:
struct A {};
struct B : A {};
struct C : A {};
struct D : B, C {} d;
template<A*> struct X;
void f(X<(A*)(B*)&d>*);
Как обычно, стандарт избегает признания существования таких вещей, как искажение, но они сильно двигаются ими.