如果可能,尝试对字符串执行静态断言,或者在不是时回退到运行时检查
try to do a static assertion on a string if possible or fallback to a runtime check when it's not
我有一个名为databaseManager的类,它可以打开受保护的共享数据库。如果数据库的名称以"#"开头,您就可以知道它受到了保护。我还有两种方法:
openProtectedDatabase(QString name)
(私有方法)openSharedDatabase(QString name)
(公共方法)
由于99.99%的时间用户将使用openSharedDatabase
,如
openSharedDatabase("I_m_a_database")
在这种特定的情况下,我希望在编译时检查他是否有权这样做(在字符串的开头不理解"#"
)。这样我就可以立即抛出错误。
以下是我开始做的事情:
bool DatabaseManager::isDatabaseProtected(QString name) {
return name[0] == '#';
}
CollaoDatabase &DatabaseManager::openSharedDatabase(QString name){
//if a static assertion is possible
//static_assert(static_assertion_possible(name) && isDatabaseProtected(name), "this database name is protected")
//run time check
if (isDatabaseProtected(name)) {
qWarning() << name + " is a protected database";
return nullptr;
}
return openProtectedDatabase(name);
}
static_assert
在编译时需要一个返回整数值的常量表达式。编译无法知道QString中有什么,因此无法静态断言它是健全的。
这是可以做到的,但您需要使用一个自定义的字符串类,该类在编译时接受文字,不允许突变,并对所有成员函数使用constexpr
。给定这个包装器实现为类myString
,执行static_assert
的代码如下所示:
constexpr unsigned beginsWithHash(myString str)
{
return str.size() > 0 && str[0] == "#";
}
static_assert(beginsWithHash(dbname), "DB Name must begin with #");
以下是更多详细信息。
编辑:代表@jarod42的评论,我应该补充一点,除非封闭函数也是constexpr,否则不能将参数从封闭函数传递给beginsWithHash
。需要给它一个直接的字符串文字。你需要做一些时髦的预处理器魔术和/或函子技巧,让它按照你想要的方式运行,并且看起来/感觉仍然干净。
好的,多亏了你的建议,我终于做了一些我想做的事情。我使用了这个问题的答案:在C++中方便地声明编译时字符串来创建一个编译时字符序列,现在有两个重载:
template <typename ct_str> inline CollaoDatabase &openSharedDatabase()
inline CollaoDatabase openSharedDatabase(QString name)
第一个是这样使用的(这个做一个静态断言):
openSharedDatabase<CT_STR("#I_m_a_protected_name")>();
第二个是这样的(这个是运行时检查):
openSharedDatabase("Hithere");
这是代码:
#define MACRO_GET_1(str, i)
(sizeof(str) > (i) ? str[(i)] : 0)
#define MACRO_GET_4(str, i)
MACRO_GET_1(str, i+0),
MACRO_GET_1(str, i+1),
MACRO_GET_1(str, i+2),
MACRO_GET_1(str, i+3)
#define MACRO_GET_16(str, i)
MACRO_GET_4(str, i+0),
MACRO_GET_4(str, i+4),
MACRO_GET_4(str, i+8),
MACRO_GET_4(str, i+12)
#define MACRO_GET_64(str, i)
MACRO_GET_16(str, i+0),
MACRO_GET_16(str, i+16),
MACRO_GET_16(str, i+32),
MACRO_GET_16(str, i+48)
#define CT_STR(str) ct_string<MACRO_GET_64(str, 0), 0>
template <char firstL, char... letters>
struct ct_string{
static char const * c_str() {
static constexpr char string[]={firstL, letters...,' '};
return string;
}
static constexpr char first() {
return firstL;
}
};
inline bool isDatabaseProtected(QString name){
return name[0] == '#';
}
template<typename ct_str> static constexpr inline bool isDatabaseProtected() {
return ct_str::first() == '#';
}
inline CollaoDatabase &openSharedDatabase(QString name){
if (isDatabaseProtected(name)) {
qWarning() << name + " is a protected database";
}
return openProtectedDatabase(name);
}
template <typename ct_str> inline CollaoDatabase &openSharedDatabase() {
static_assert(!isDatabaseProtected<ct_str>(), "you are trying to open a protected database");
return openProtectedDatabase(QString(ct_str::c_str()));
}
相关文章:
- 在运行时检查继承是否只有一种类型和 void*
- 运行时检查失败 #2 变量"A"周围的堆栈已损坏
- 运行时错误:矢量下标超出范围:正在检查空集
- 运行时检查失败 #0 用于运行时重新编译
- 运行时检查失败 #2 - 变量"e"周围的堆栈已损坏。发生
- 运行时检查失败 #2 MSVC 仅使用 utf8proc 进行调试
- 使用 SET(C++) 检查两个给定字符串是否是字谜时出现运行时错误
- std::copy 导致运行时检查失败 #2
- 运行时检查失败 #2 - 变量周围的堆栈'...'已损坏
- 积分转换的运行时检查
- 运行时检查失败 #2 - 变量"l1"周围的堆栈已损坏
- 自上而下的动态规划与递归朴素解决方案.检查运行时执行
- C++:此代码可以编译,但引发运行时检查失败 #2 - 围绕变量周围的堆栈'num'已损坏。发生
- 运行时检查失败 - 变量周围的堆栈已损坏
- swscanf_s - 运行时检查错误
- 如何在void*指针下检查运行时类型(允许简单类型,没有基类)?
- 正在检查运行时是否支持SSE
- 检查运行时操作系统上运行的语言
- 检查运行时错误 #2
- 在c++中检查运行时的可转换性