编译时断言用于字符串相等

时间:2011-04-19 19:47:27

标签: c++ templates metaprogramming

这可以使用模板吗?

有两个字符串常量。它们来自不同模块中的定义。它们必须相等,否则如果它们不相等,我将引发编译时错误。我可以使用模板吗?

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

P.S。假设“abc”[0]是常量表达式,我被迷惑了。它不是。在语言中奇怪的遗漏。如果“abc”[0]是常量表达式,那将是可能的。

2 个答案:

答案 0 :(得分:20)

这只适用于C ++ 0x。没有机会使用C ++ 03。

编辑:C ++ 0x的Constexpr函数。下面的内容适用于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

答案 1 :(得分:-3)

没有。你不能。甚至没有boost::mplboost预处理器库。即使您要规定编译器可以在编译时将所有重复的字符串引用合并到相同的指针值,指针值也会在链接时间之前存在。你想要实现的是在预处理器时发生,然后在编译时断言。