20

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.

Avba
  • 13,954
  • 15
  • 87
  • 165
  • Are you assuming string literal pooling also Related to [Computing length of a C string at compile time. Is this really a constexpr?](http://stackoverflow.com/q/25890784/1708801) – Shafik Yaghmour Dec 15 '14 at 18:46

4 Answers4

19

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

Jan Herrmann
  • 2,607
  • 15
  • 21
18

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.

cdhowie
  • 144,362
  • 22
  • 272
  • 285
  • that was using coliru on the same website. tried it on clang with 1y, works fine. will delete my comment. – Richard Hodges Dec 15 '14 at 18:54
  • I am trying to get this to work in Xcode - wasn't able to . Maybe there is another way to make a static assert in that environment. I found a few resources but wasn't able to get it to work. http://en.cppreference.com/w/cpp/language/static_assert – Avba Dec 16 '14 at 10:49
  • "the caveat that many compilers will compile equal string literals to be a pointer to the same location." String literals do not have memory locations. – Nils Jul 17 '19 at 08:46
  • 1
    @Nils A string literal creates an unnamed array with static storage duration. This array has a memory location, which is what the literal effectively refers to. So yes, a literal causes a memory location to exist, which can be compared as with any other pointer. – cdhowie Jul 17 '19 at 13:42
10

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.

Columbo
  • 58,324
  • 8
  • 149
  • 196
2

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

Community
  • 1
  • 1
NathanOliver
  • 161,918
  • 27
  • 262
  • 366