How can you compare two character strings statical

2019-02-12 17:09发布

问题:

I would like to create a macro which can compare 2 strings, and emit a compile time error if the condition isn't met. This could be though of as a compile time assertion.

I'm not sure how I could do this.

For instance:

STATIC_COMPARE("THIS STRING","THIS STRING") -> would emit a compile time error
STATIC_COMPARE("THIS STRING","THIS OTHER STRING) -> wouldn't emit a compile time error.

The macro would look something like

#define STATIC_COMPARE(str1,str2) if (str1==str2) emit an error with a message

So I guess the question boils down to being able to compare the 2 strings at compile time.

回答1:

You can do this with C++11 by using a constexpr function:

constexpr bool strings_equal(char const * a, char const * b) {
    return *a == *b && (*a == '\0' || strings_equal(a + 1, b + 1));
}

(See a demo)

It's not possible to do this prior to C++11, with the caveat that many compilers will compile equal string literals to be a pointer to the same location. On these compilers it's sufficient to compare the strings directly since they will both be evaluated as equal pointers.



回答2:

You can use constexpr functions. Here's the C++14 way:

constexpr bool equal( char const* lhs, char const* rhs )
{
    while (*lhs || *rhs)
        if (*lhs++ != *rhs++)
            return false;
    return true;
}

Demo.



回答3:

This can be done in C++ 11 using constexpr. By defining a recursive function you can check that the string are equal or not.

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");

This code I used thanks to Johannes Schaub and you can see the full SO post here



回答4:

Starting with C++17 std::string_view is available. It supports constexpr comparisson:

#include <string_view>

constexpr bool strings_equal(char const * a, char const * b) {
    return std::string_view(a)==b;
}

int main() {
    static_assert(strings_equal("abc", "abc" ), "strings are equal");
    static_assert(!strings_equal("abc", "abcd"), "strings are not equal");
    return 0;
}

Demo