0
对于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);
}
};
它非常好,但它仍然有可能要创建从自动存储时间阵列一个文字。我希望在编译时避免这种情况。下面的例子是未定义行为:
#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找到。是否有可能在编译时检测到这个用例并强制编译错误?
你为什么不坚持使用该文本操作方式 – Sopel
其实我们使用的文字有一段时间了,从来没有绊倒在这个陷阱,因为我们的开发人员通常采取的字面操作方式。另一方面,如果一个开发人员出于任何原因编写这样的构造,我宁愿在编译时捕获它,而不是无尽的调试会话。 –
听起来你应该只是使应用构造函数的私人和文本操作模板的朋友。 –