Logo

Blog


Equality of a string class that is only instantiable at compile-time

Today's post continues with last month's post A string class that is only instantiable at compile-time.

Jonathan O'Connor approached me with an interesting observation I like to share. Here is the implementation again:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Literal {
  const char* const mData{};
  const size_t      mLen{};

  friend constexpr Literal operator""_l(const char* data, size_t len);

  constexpr Literal(const char* data, size_t len)
  : mData{data}
  , mLen{len}
  {}

public:
  // imagine the access functions you need
};

constexpr Literal operator""_l(const char* data, size_t len)
{
  return {data, len};
}

Jonathan noticed that since the Literal objects are all created during compile-time, all instances with the same string should share the same pointer to the c-string. This then makes comparing them for equality simple because all we have to do is check whether the pointers are equivalent:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Literal {
  const char* const mData{};
  const size_t      mLen{};

public:
  consteval Literal(const char* data, size_t len)
  : mData{data}
  , mLen{len}
  {}

public:
  bool operator==(const Literal& rhs) const { return mData == rhs.mData; }

  // imagine the access functions you need
};

consteval Literal operator""_l(const char* data, size_t len)
{
  return {data, len};
}

The following code passes on my local machine and Compiler Explorer:

1
2
3
4
auto a = "Hello"_l;
auto b = "Hello"_l;

assert(a == b);

However, the implementation relies on the optimization behavior of the compiler. While it looks like it works, it can also break. Please keep that in mind.

[Update 7. Feb. 2023]: As Daniela Engert pointed out on Twitter, the standard deems the behavior unspecified: [lex.string p9]

Andreas