Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to represent Nullable member in C++? [duplicate]

Possible Duplicate:
Nullable values in C++

What is the best way to represent nullable member in C++?

In C#, we can use Nullable<T> type. Such a data type is very much needed as not everything can have meaningful value. It is so important data type that @Jon Skeet has spent one entire chapter, spanned over 27 pages, describing only Nullable<T> in his outstanding book C# in Depth.

One simple example can be a Person class1, defined as:

struct Person
{
  std::string Name;
  DateTime    Birth;
  DateTime    Death;
  //...
};

As a person always have birthdate, so the Birth member of the above class will always have some meaningful value. But how about Death? What should it value be if the person is alive? In C#, this member can be declared as Nullable<DataTime>2 which can be assigned with null if the person is alive.

In C++, what is the best way to solve this? As of now, I've only one solution in mind: declare the member as pointer:

 DataTime *Death;

Now its value can be nullptr when the person is alive. But it forces the use of new for dead person, as it's going to have some valid value. It in turn implies one cannot rely on the default copy-semantic code generated by the compiler. The programmer has to write copy-constructor, copy-assignment, destructor following rule of three (C++03), Or in C++11, rule of five.

So do we have any better, elegant solution to this problem than just making it pointer?


1. Other examples include relational database tables, as in many DBMSs columns can be nullable.

2. There is also a shorthand for this. One can write DataTime? which is exactly same as Nullable<DateTime>.

like image 308
Nawaz Avatar asked Oct 04 '11 09:10

Nawaz


People also ask

Which of the following is best represented by a nullable type?

You typically use a nullable value type when you need to represent the undefined value of an underlying value type. For example, a Boolean, or bool , variable can only be either true or false . However, in some applications a variable value can be undefined or missing.

How do I create a nullable double in C#?

You can declare nullable types using Nullable<t> where T is a type. Nullable<int> i = null; A nullable type can represent the correct range of values for its underlying value type, plus an additional null value. For example, Nullable<int> can be assigned any value from -2147483648 to 2147483647, or a null value.

What is the use of HasValue in C#?

Nullable types have two properties. HasValue: This property returns a bool value based on that if the Nullable variable has some value or not. If the variable has some value, then it will return true; otherwise, it will return false if it doesn't have value or it's null.

Should I use nullable reference types?

Although using nullable reference types can introduce its own set of problems, I still think it's beneficial because it helps you find potential bugs and allows you to better express your intent in the code. For new projects, I would recommend you enable the feature and do your best to write code without warnings.


2 Answers

You could look into Boost.Optional:

struct Person {   std::string               Name;   DateTime                  Birth;   boost::optional<DateTime> Death;   //... }; 
  • Your Death is "uninitialised" at first.
  • You can then assign a value to it with =, like Death = myDateTime.
  • When Death.is_initialized(), you can use Death.get().
  • Uninitialise it again with Death.reset().

For simple cases like this, though, it's usually considered more coherent to just pick your own blatant sentinel value like, say, a DateTime of "0000-00-00 00:00:00".

like image 137
Lightness Races in Orbit Avatar answered Sep 20 '22 11:09

Lightness Races in Orbit


Depends on DateTime - like @Tomalak says in his answer, boost::optional<> is a generic solution. However if for example your DateTime is a boost::posix_time::ptime, then there is already support for special values (for example not_a_date_time or pos_infin) - you could use these.

like image 40
Nim Avatar answered Sep 23 '22 11:09

Nim