Утверждение времени компиляции для равенства строк - PullRequest
17 голосов
/ 19 апреля 2011

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

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

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

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

Ответы [ 2 ]

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

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

EDIT: функция Constexpr для C ++ 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 .

0 голосов
/ 19 апреля 2011

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

...