Подтвердить что ты не робот

Утверждение времени компиляции для равенства строк

Можно ли это сделать с помощью шаблонов?

Есть две строковые константы. Они исходят из определений в разных модулях. Они должны быть равны, или я буду поднимать ошибку времени компиляции, если они не равны. Могу ли я сделать это с помощью шаблонов?

#define MY_STRING "foo"
CompileAssertIfStringsNotEqual(MY_STRING, HIS_STRING);

P.S. Я был введен в заблуждение, предположив, что "abc" [0] является постоянным выражением. Это не. Странное упущение на этом языке. Было бы возможно, что "abc" [0] было константным выражением.

4b9b3361

Ответ 1

Это возможно только с С++ 0x. Нет шансов с С++ 03.

EDIT: функция Constexpr для С++ 0x. Следующее работает с GCC4.6, однако Стандарт не является явным в его разрешении, и небольшая корректировка формулировок была и рассматривается как позволяющая спецификации разрешить это.

constexpr bool isequal(char const *one, char const *two) {
  return (*one && *two) ? (*one == *two && isequal(one + 1, two + 1))
    : (!*one && !*two);
}

static_assert(isequal("foo", "foo"), "this should never fail");
static_assert(!isequal("foo", "bar"), "this should never fail");

Компилятор должен отслеживать ссылку на символы строковых литералов уже во всех рекурсиях. Только окончательное чтение из символов явно не разрешено (если вы косоглазие, вы можете прочитать его как разрешенное, IMO). Если ваш компилятор не хочет принимать вышеуказанную простую версию, вы можете сделать свой макрос объявлением массивов, а затем сравнить их

#define CONCAT1(A, B) A ## B
#define CONCAT(A, B) CONCAT1(A, B)

#define CHECK_EQUAL(A, B) \
  constexpr char CONCAT(x1, __LINE__)[] = A, \
                 CONCAT(x2, __LINE__)[] = B; \
  static_assert(isequal(CONCAT(x1, __LINE__), CONCAT(x2, __LINE__)), \
     "'" A "' and '"  B "' are not equal!")

Это определенно хорошо.

CHECK_EQUAL("foo", "foo"); /* will pass */
CHECK_EQUAL("foo", "bar"); /* will fail */

Обратите внимание, что CHECK_EQUAL может использоваться внутри функций. FCD сделал изменения, чтобы позволить функциям constexpr читать из автоматических массивов в их замене вызова. См. DR1197.

Ответ 2

Нет. Ты не можешь. Даже с boost::mpl или препроцессором boost. Даже если вы должны были оговаривать, что компилятор может объединить все повторяющиеся ссылки на строки в одно и то же значение указателя во время компиляции, значение указателя не существует до момента ссылки. То, что вы хотите реализовать, происходит во время препроцессора, а затем утверждается во время компиляции.