Skip to content

Instantly share code, notes, and snippets.

@bekasov
Last active August 29, 2015 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bekasov/1e30ba3c29388b4f1627 to your computer and use it in GitHub Desktop.
Save bekasov/1e30ba3c29388b4f1627 to your computer and use it in GitHub Desktop.
C++ Nullable Type Template
#ifndef NULLABLETYPE_H
#define NULLABLETYPE_H
template <class T>
class NullableType
{
protected:
T* value;
public:
NullableType<T>() : value(NULL) {};
NullableType<T>(T value)
{
this->value = new T(value);
};
NullableType<T>(T* value)
{
if (value != NULL) {
this->value = new T(*value);
} else {
this->value = NULL;
}
};
NullableType<T>(const NullableType<T>& value)
{
T* tmp = (T*)value;
if (tmp == NULL) {
this->value = NULL;
} else {
this->value = new T(*tmp);
}
};
virtual ~NullableType<T>()
{
if (this->value != NULL) {
delete this->value;
}
};
/*
virtual operator T()
{
if (this->value == NULL) {
T tmp;
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#pragma GCC diagnostic ignored "-Wuninitialized"
return tmp;
#pragma GCC diagnostic warning "-Wmaybe-uninitialized"
#pragma GCC diagnostic warning "-Wuninitialized"
//return 0;
}
return *this->value;
}
*/
virtual operator T*() const
{
return this->value;
}
virtual NullableType<T>& operator=(const T* const value)
{
if (NULL == value) {
if (this->value != NULL) {
delete this->value;
}
this->value = NULL;
return *this;
}
if (this->value == NULL) {
this->value = new T(*value);
} else {
*this->value = *value;
}
return *this;
}
virtual NullableType<T>& operator=(const T& value)
{
if (NULL == &value) {
if (this->value != NULL) {
delete this->value;
}
this->value = NULL;
return *this;
}
if (this->value == NULL) {
this->value = new T(value);
} else {
*this->value = value;
}
return *this;
}
virtual NullableType<T>& operator=(const NullableType<T>& value)
{
if (this == &value) {
return *this;
}
T* tmp = (T*)value;
if (tmp == NULL) {
if (this->value != NULL) {
delete this->value;
}
this->value = NULL;
} else {
if (this->value == NULL) {
this->value = new T;
}
*this->value = *tmp;
}
return *this;
}
};
#endif
@bekasov
Copy link
Author

bekasov commented Nov 9, 2014

Usage:

class FooModel 
{
public:
     NullableType<int> intParam;
};

FooModel* model = new FooModel();

bool resBool = model->intParam == nullptr; // true
model->intParam = 654; // works operator=(int)
resBool = model->intParam == nullptr; // false

NullableType<int> globIntParam1 = model->intParam; // works copy ctor

model->intParam = (int*)NULL; // works operator=(const int*), no memory leaks

globIntParam1 = model->intParam; // works operator=

int* intVarPtr1 = new int(23);
int* intVarPtr2 = NULL;
model->intParam = intVarPtr1; // works operator=(const int*)
model->intParam = intVarPtr2;

model->intParam = nullptr; // without (int*)NULL

NullableType<int> globIntParam2(22); // works ctor(int)
NullableType<int> globIntParam3(intVarPtr); // works ctor(int*)

@bekasov
Copy link
Author

bekasov commented Nov 9, 2014

There is a issue:
For NullableString:

    virtual operator T()
        {
            if (this->value == NULL) {
            return 0;
        } 
...

Need to return the empty string - "".

If replace "return 0" to:

      T tmp;
      return tmp;

The compiler gives many warnings about unitialized variable, but all works well.

        #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
        #pragma GCC diagnostic ignored "-Wuninitialized"
        return tmp;
        #pragma GCC diagnostic warning "-Wmaybe-uninitialized"
        #pragma GCC diagnostic warning "-Wuninitialized"

@sarum9in
Copy link

Try "return T();"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment