对于a similar SO question,我想出了以下解决方案:
#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);
}
};
它运行良好,但仍然可以从具有自动存储持续时间的阵列创建Literal。我想在编译时阻止它。以下示例具有未定义的行为:
#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;
}
也可以在godbolt compiler explorer找到它。是否有可能在编译时检测到这个用例并强制编译错误?
答案 0 :(得分:0)
不,这是不可能的。 okay
,boom
和相同大小的字符串文字都具有相同的类型,并且无法区分为表达式。