【问题标题】:Compile-time assert for string equality字符串相等的编译时断言
【发布时间】:2011-08-08 23:20:54
【问题描述】:

这可以使用模板吗?

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

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

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

【问题讨论】:

    标签: c++ templates metaprogramming


    【解决方案1】:

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

    编辑:C++0x 的 Consexpr 函数。以下适用于 GCC4.6,但标准并未明确允许它,并且正在考虑对措辞进行小幅调整以使规范允许它。

    constexpr bool isequal(char const *one, char const *two) {
      *one == *two && (!*one || isEqual(one + 1, two + 1));
    }
    
    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 但是,我一直怀疑在使用元编程的 C++ 中这可能是可能的。但我从来没有能够完成它。随着 C++0x 的出现,我放弃了尝试。
    • 这意味着可以用 C++ 模板语言编写编译器。哇哦!
    • 我已经看到一些 boost 人提出了一个模板化的“DSL”,它被转换为一系列 constexpr 函数调用:) 对他们来说只是时间问题。
    • 我认为将两个额外的参数传递给 isequal() —— sizeof(string1) 和 sizeof(string2),使得 isequal 对你暗示的不兼容性的依赖性降低。
    • 最大字符串长度取决于为具体编译器定义的最大递归堆栈大小。 不确定,但据我所知,通常是 256
    【解决方案2】:

    没有。你不能。即使使用 boost::mplboost 预处理器库也不行。即使您规定编译器可以在编译时将所有重复的字符串引用合并到相同的指针值中,该指针值直到链接时才存在。您要实现的内容发生在预处理器时,然后在编译时被断言。

    【讨论】:

    • 然而,模板不接受“带引号的字符串”进行专业化。
    • 他们也不接受 doublefloat 或任何其他非整数值用于专门化 template something<int N>
    • 然而编译时模板计算双打是可能的 -> tinyurl.com/6k9ry65
    猜你喜欢
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多