我正在尝试对赋值进行编译时检查,并针对null进行测试。原因是我正在使用“魔术”非空指针来表示某事物的脱离状态,并且很容易忘记它正在使用该魔术指针并错误地分配和测试nullptr。 (特别是因为这是该代码在历史上一直使用的。)
发现这是人们已经解决的问题,我搜索发现not_null
为part of the C++ Core Guidelines,这听起来很有希望。这是Microsoft的MIT许可实施:
但是它只会停止分配给nullptr,而不是进行比较:
#include <iostream>
#include "include/gsl/gsl"
int main() {
int i;
gsl::not_null<int*> ptr (&i);
/* gsl::not_null<int*> ptr_error (nullptr); */ // this errors
if (ptr != nullptr)
std::cout << "No compile error on compare--this prints\n";
}
那是...不幸的。 :-/
难道不是指导程序员帮助编码程序语义的核心准则吗?
对not_null
进行较小的修改是什么,将其更改为不允许进行这些比较,例如nullptr == ptr
,ptr == nullptr
等?蛮力我只是{= {1}}对==和!=进行一些重载,直到在我想要的情况下给出错误为止,但是我希望使用预先编写的代码是有人会考虑并做得更多通常是“正确”。
答案 0 :(得分:1)
之所以这样做,可能是因为有时您可能会获得一个指针/智能指针,并希望将其与gsl::not_null
进行比较,并且/或者将gsl::not_null
传递给模板函数(绝对不知道gsl::not_null
提供了什么):
template<class Lhs, class Rhs>
bool hasSameValue(Lhs lhs, Rhs rhs){
if(lhs == nullptr || rhs == nullptr)
return lhs == rhs;
return *lhs == *rhs;
}
gsl::not_null<int*> ptr = /* [...] */;
shared_ptr<int> sptr = /* [...] */;
hasSameValue(ptr, sptr);
如果您仍然想禁止使用nullptr
进行检查:
bool operator==(std::nullptr_t nptr) = delete;
bool operator!=(std::nullptr_t nptr) = delete;
将它们标记为已删除就足够了。请注意,gsl::not_null
不得继承自定义它们的类。如果它继承自定义它们的类,则只需引发一个异常(即使它只是运行时错误)。
答案 1 :(得分:0)
您只需要为std::nullptr_t
类型实现相等运算符:
// Example program
#include <iostream>
#include <string>
class Test
{
public:
Test(int value) : value(value) {}
bool operator == (std::nullptr_t n)
{
return value == 0;
}
bool operator != (std::nullptr_t n)
{
return value != 0;
}
private:
int value;
};
int main()
{
Test a(0);
Test b(1);
std::cout << (a == nullptr) << ", " << (b == nullptr) << "\n";
std::cout << (a != nullptr) << ", " << (b != nullptr) << "\n";
}
或者如果您想要编译错误,只需删除相同的运算符即可。