将传递的参数限制为非临时字符串文本
Restrict passed parameter to a non-temporary string literal
对于类似的SO问题,我想出了以下解决方案:
#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("%sn", okay().c_str()); // <= the intended use case
printf("%sn", boom().c_str()); // <= the undefined behaviour
return 0;
}
它也可以在godbolt编译器资源管理器中找到。是否可以在编译时检测到此用例并强制编译错误?
不,这是不可能的。 okay
、boom
和相同大小的字符串文本都具有相同的类型,并且不能作为表达式区分。
相关文章:
- 如何在C++中用std::cout正确显示带十六进制的字符串文本
- 在编译时检查字符串文本的长度
- 读取字符串文本输入以创建 2D 矢量
- 管理字符串文本的最佳做法
- 定义宏以将前缀 0x 添加到十六进制字符串文本
- 无法在模板参数中定义字符串文本
- 不推荐使用 PTCHAR 的字符串文本
- C++ 字符串文本和常量
- C++20字符串文本模板参数工作示例
- 返回从字符串文本创建的静态string_view是否安全?
- 在处理任何字符大小的模板中使用字符串文本
- 是否保证相同内容字符串文本的存储相同?
- 将以 null 结尾的字节字符串转换为原始字符串文本
- 是否可以创建一个用户定义的文本,将字符串文本转换为 own 类型的数组?
- 使用C++中的模板检测不同的字符串文本
- 无法完全专用化字符串文本的模板
- C++ - 确定 const char* 是指向字符串文本对象还是动态对象
- 是否可以在原始字符串文本中插入转义序列?
- C++带有捕获组的正则表达式字符串文本
- 为什么多维数组中的空字符串文本衰减为空指针?