0

For a similar SO question I came up with the following solution:

#include <cstdlib>

class Literal
{
  public:

    template <std::size_t N> constexpr
    Literal(const char (&str)[N])
    : mStr(str),
      mLength(checkForTrailingZeroAndGetLength(str[N - 1], N))
    {
    }

    template <std::size_t N> Literal(char (&str)[N]) = delete;

    constexpr operator const char*() const noexcept
    {
        return mStr;
    }

    constexpr const char* c_str() const noexcept
    {
        return mStr;
    }

  private:
    const char* mStr;
    std::size_t mLength;

    struct Not_a_CString_Exception{};

    constexpr static
    std::size_t checkForTrailingZeroAndGetLength(char ch, std::size_t sz)
    {
      return (ch) ? throw Not_a_CString_Exception() : (sz - 1);
    }
};

It works very well, but it is still possible to create a Literal from arrays with automatic storage duration. which I would like to prevent at compile time. The following example has undefined behaviour:

#include <cstdio>

static Literal okay()
{
    static constexpr const char okay[] = "okay";
    return { okay };
}

static Literal boom()
{
    const char boom[] = "boom"; //Oops, static forgotten
    return { boom }; // <= How to force a compile error here?
}

int main()
{
    printf("%s\n", okay().c_str()); // <= the intended use case
    printf("%s\n", boom().c_str()); // <= the undefined behaviour
    return 0;
}

It can also be found at godbolt compiler explorer. Is it possible to detect this use case at compile time and force an compile error?

k.st.
  • 41
  • 4
  • why don't you stick with the literal operator way – Sopel Jun 22 '17 at 11:04
  • Actually we are using Literal for a while now and never stumbled over this trap, because our developers usually take the literal operator way. On the other hand if one developer writes such an construct for whatever reason, I would prefer to catch it at compile time rather then endless debugging sessions. – k.st. Jun 22 '17 at 11:21
  • 1
    Sounds like you should just make the applicable ctor private and the literal operator template a friend. – T.C. Jun 22 '17 at 17:52

1 Answers1

0

No, this is not possible. okay, boom, and a string literal of the same size all have the same type and are not distinguishable as expressions.

aschepler
  • 70,891
  • 9
  • 107
  • 161