Индекс константы времени компиляции в массив констант времени компиляции сам по себе является константой времени компиляции? - PullRequest
2 голосов
/ 20 апреля 2009

Я пытаюсь играть в причудливые игры, в которых компилятор C ++ синтезирует хэш-значения константных строк во время компиляции. Это позволило бы мне заменить строку одним идентификатором, что позволило бы существенно сэкономить на размере и сложности кода.

Для ясности и простоты программирования было бы замечательно, если бы я мог исследовать и вычислять во время компиляции с помощью простых встроенных символьных строк, таких как "Hello", которые являются указателями на константу времени компиляции на константы времени компиляции.

Если я могу индексировать их во время компиляции, я могу создать шаблонную метапрограмму, чтобы делать то, что я хочу. Но неясно, рассматривает ли стандарт C ++ индекс ct-константы массива ct-constant как ct-константу сам по себе.

Спросил иначе,

 const char v="Hello"[0];

вполне допустимо C ++ (и C). Но является ли значение v постоянной времени компиляции?

Я уже верю, что ответ отрицательный, но на практике некоторые компиляторы принимают его даже без какого-либо предупреждения, а тем более с ошибкой. Например, следующий код компилируется и запускается без единого предупреждения от компилятора Intel C ++:

#include <iostream>
const char value="Hello"[0];
template<char c>  void printMe()
{
  std::cout << "Template Val=" << c << std::endl;
}

int main()
{
  const char v='H';
  printMe<'H'>();
  printMe<v>();
  printMe<value>(); // The tricky and interesting case!
}

Тем не менее, компилятор Microsoft не будет компилироваться вообще, выдавая достаточно логичное сообщение об ошибке при использовании шаблона с объектом с внутренней связью.

Я подозреваю, что ответ на мой вопрос: «Нет, вы не можете предполагать, что любая ссылка на массив, даже на постоянный массив с постоянным индексом, является постоянной во время компиляции». Означает ли это, что успешное выполнение компилятора Intel является ошибкой в ​​компиляторе Intel?

Ответы [ 3 ]

2 голосов
/ 20 апреля 2009

Это также не работает в GCC.

Однако , вне точки зрения соответствия языку, приятно, что оптимизатор компилятора обрабатывает его как символьную константу, в значительной степени. Я использовал этот факт для разрешения генерируемых препроцессором символьных констант (используя *#foo). См. http://cvs.openbsd.org/cgi-bin/query-pr-wrapper?full=yes&numbers=1652, в файле hdr.h. С этим макросом вы можете написать

DECR(h, e, l, l, o)

, а не

DECR('h', 'e', 'l', 'l', 'o')

Гораздо более читабельно, на мой взгляд. : -)

1 голос
/ 20 апреля 2009

Хороший вопрос, да, это можно сделать, и это нормально со стандартами, и это будет работать на Microsoft, GCC и Intel, проблема в том, что у вас неправильный синтаксис:)

Одну секунду я приготовлю образец ... Хорошо сделано, вот оно. Этот пример является допустимым C ++, и я использовал его довольно часто, но на самом деле большинство программистов не знают, как сделать это правильно.

template<char* MSG>
class PrintMe
{
public:
    void operator()()
    {
        printf(MSG);
    }
};

char    MyMessage[6] = "Hello"; //you can't use a char*, but a char array is statically safe and determined at compiletime

int main(int argc, char* argv[])
{
    PrintMe<MyMessage> printer;
    printer();
    return 0;
}
0 голосов
/ 20 апреля 2009

Соответствующая разница здесь - это разница между «выражением интегральной константы» и простой константой времени компиляции «3.0» - это константа времени компиляции. int (3.0) также является константой времени компиляции. Но только «3» - это ЛЕД. [См. 5.19]

Подробнее на boost.org

...