I tried to write a nullptr_t
class based on the official proposal to be used in C++03 only. The only differences with the proposal are that we can compare two nullptr_t
instances and that it is convertible to bool
via an overload to void*
to avoid unwanted behaviour such as int a = nullptr;
for example. Here is the class:
const class nullptr_t
{
public:
// Return 0 for any class pointer
template<typename T>
operator T*() const
{
return 0;
}
// Return 0 for any member pointer
template<typename T, typename U>
operator T U::*() const
{
return 0;
}
// Used for bool conversion
operator void*() const
{
return 0;
}
// Comparisons with nullptr
bool operator==(const nullptr_t&) const
{
return true;
}
bool operator!=(const nullptr_t&) const
{
return false;
}
private:
// Not allowed to get the address
void operator&() const;
} nullptr = {};
I would like to know if there is any actual flaw in this completed implementation or if there is a difference in the behaviour compared to the C++11 type std::nullptr_t
besides the namespace that I can't see.
2 Answers 2
At the moment, your implementation allows
auto& p = nullptr;
This is forbidden in C++11 as nullptr
is an rvalue. You also do not allow the following:
auto p = nullptr;
auto pp = &p;
While C++11 does allow it. You are also missing overloads for comparison operators.
A simple workaround would be to remove the operator&
overload and add a macro:
#define nullptr (nullptr_t())
Also, I'd generally use struct X { ... } const x;
instead of const struct X { ... } x;
.
Another thing I forgot at the time is that the standard specifies that sizeof(nullptr)
shall be equal to sizeof(void*)
.
3.9.1 - Fundamental types
3.9.1.10 A value of type
std::nullptr_t
is a null pointer constant (4.10). Such values participate in the pointer and the pointer to member conversions (4.10, 4.11).sizeof(std::nullptr_t)
shall be equal tosizeof(void*)
.
So technically speaking, I should have added padding to my class
:
class nullptr_t
{
// To ensure the size
// Should be correctly aligned
void* padding;
// ...
} const nullptr;
-
1\$\begingroup\$ Could you provide full implementation including C++11 improvements to nullptr ... I would be grateful. \$\endgroup\$Leo– Leo2016年07月10日 21:44:11 +00:00Commented Jul 10, 2016 at 21:44
-
\$\begingroup\$ That
sizeof
requirement is a nuisance. I see two issues with adding thatpadding
: 1) I'm not sure that copying around an uninitializedvoid *
is well-defined. I considered replacing it withunsigned char padding[sizeof(void *)]
, but that didn't solve the next issue, nor would adding empty copy operators. 2) Including aprivate
non-static
member variable breaks POD-ness, at least before C++11. I don't see a good way around this. \$\endgroup\$Joshua Green– Joshua Green2018年06月19日 11:27:32 +00:00Commented Jun 19, 2018 at 11:27
Explore related questions
See similar questions with these tags.