Create objects in conditional c++ statements - c++

I am learning c++, and I just got to the object oriented chapter. I have a question about creating objects inside if statements.
The problem I'm working on says to create a class that will display a report header. The class has a default constructor that sets the company name and report name to a generic thing, and also, if the user wants, has a constructor that takes two arguments (strings company name and report name).
The problem says, specifically, "A two-parameter default constructor should allow these [company and report names] to be specified at the time a new Report object is created. If the user creates a Report object without passing any arguments, use the default values. Otherwise, use user specified values for the names."
So my question is, how to create these objects? I understand how to create an object without any arguments (i.e. Report newobj;), and also with arguments (i.e. Report newobj(string string);). Basically, I get how to create these objects initially at the top of my main function. But is it possible to create them inside if statements based on user choices? Here is what I have so far and, obviously, it doesn't work:
#include <iostream>
#include <string>
#include "report.h"
using namespace std;
bool enter_company_name(); // return true if user wants to enter company name
bool print_form(); // return true if user wants to print in formatted output
int main()
{
string company_name,
report_name;
bool name = false,
format = false;
name = enter_company_name();
format = print_form();
if (name)
{
cout << "Enter company name: ";
getline(cin, company_name);
cout << "Enter report name: ";
getline(cin, report_name);
Report header(company_name, report_name); // THIS IS MY PROBLEM
}
else
Report header; // THIS IS MY PROBLEM
if (format)
header.print_formatted();
else
header.print_one_line();
return 0;
}
bool enter_company_name()
{
char choice;
cout << "Do you want to enter a name?\n>";
cin >> choice;
if (choice == 'y' || choice == 'Y')
return true;
else
return false;
}
bool print_form()
{
char choice;
cout << "Do you want to print a formatted header?\n>";
cin >> choice;
if (choice == 'y' || choice == 'Y')
return true;
else
return false;
}
So I want to create an object using default values if none are specified, or create one with the user values if that's the choice given. I just can't figure out how to do it interactively in c++. I have not been able to find any similar questions anywhere so far.
The closest thing I've come across uses pointers to do something similar to what I want to do, but the book I'm using has not gotten to pointers yet, and I want to try to figure out a way to do it that stays within the bounds of the chapter I'm working in (i.e. not using pointers).
I didn't include the header file or class implementation file because I don't think they are relevant here.
Thank you in advance!

First off, you cannot create an object within a conditional statement and use it after the conditional statement: the two branches of the conditional statement create a scope each and any object created within in destroyed a the end of the branch. That is, you need to come up with a different approach. The simplest approach is probably to delegate the creation of the object to a function which returns the objects as appropriate:
Report makeReport() {
if (enter_company_name()) {
...
return Report(name, company);
}
return Report();
}
...
Report report = makeReport();
An alternative approach is to use the ternary operator to conditonally create the Report one way or another:
bool get_company_name = enter_company_name();
std::string name(get_company_name? read_name(): "");
std::string company(get_company_name? read_company(): "");
Report report = get_company_name? Report(name, company): Report();
All of these approaches assume that the Report class is actually copyable.

I don't know if I understood your question correctly but can't you just declare report before the if/else block and then initialize inside it?
Report header;
if (...) {
header = Report();
else
header = Report(name,company);
Or in a shorter way:
Report header; // calls default constructor
if (shouldInitializeWithParams) {
header = Report(name,company);
}
Of course this requires you to have the empty constructor defined.

We don't know whether class Report is copy-able, so better to use pointers.
Report * header;
if (...) {
header = new Report();
else
header = new Report(name,company);
// after all don't forget
delete header;
and of course you should use header pointer like that
header->print_formatted();

The simplest thing that comes to mind is performing a little refactoring on the code flow. Create a function that processes the input and returns the constructed object:
Report loadReport() {
if (user_input()) {
// read input
return Report(name,company);
} else {
return Report();
}
}
Then call the function from main. The small change in the design is the introduction of a function whose single responsibility is creating a Report from user input, which actually makes sense as a function.

You can use an rvalue reference to bind in place to either constructed object.
struct Foo
{
Foo(int bar): bar(bar) {}
int bar
};
Foo&& f = condition ? Foo(4) : Foo(5);
f.bar = 1000;

I'm not sure if I understood your question properly. Apologies if you read the answer and realise that that's the case.
But nevertheless, I think the main strategy would be to make use of constructor overloading. ie, you define constructors for both: the case when no parameters are passed and the case when parameters are passed.
The former(what you refer to as default constructor) will initialise the company and report names to default values. The latter will assign the parameters received, to the comapany and report names.
As for the use of pointers: you can avoid it by 'declaring' a lot of objects of type 'Report'(class). For eg, you can create an array of header(objects).
And then you can 'define' it as and when the user responds.
But by using pointers, you're doing everything in runtime(dynamic assignment) whereas when using arrays(or declaring many objects): the amount is fixed. This can be inefficient.

As of C++17, you can now use std::optional for this task - it avoids dynamic memory allocation, it avoids two-phase construction of the object, and it doesn't require the type to be movable or copyable. It allows you to delay the construction of the object while keeping it on the stack and also still being exception-safe. If you construct it in every branch you can safely use it afterward with no performance penalty. It will also work as a class member allowing you to avoid the problem with the class constructor initializer for it, unlike the rvalue reference solution. Demo: https://gcc.godbolt.org/z/vbe5eh
#include <optional>
struct UseCtorA final {};
struct UseCtorB final {};
struct Report final
{
Report() = delete;
Report(Report const &) = delete;
Report(Report &&) = delete;
Report &operator=(Report const &) = delete;
Report &operator=(Report &&) = delete;
Report(UseCtorA, char c) : v{1} { if(c == 't'){ throw 3; } }
Report(UseCtorB) : v{2} {}
constexpr auto getValue() const noexcept { return v; }
private:
int v;
};
int main(int nargs, char const *const *args)
{
std::optional<Report> report;
if(nargs > 2)
{
report.emplace(UseCtorA{}, args[1][0]);
}
else
{
report.emplace(UseCtorB{});
}
return report->getValue();
}
If you are stuck in an older compiler that only supports C++11, you can make your own really dumb version of std::optional for this express purpose by using a union and placement new:
struct Empty final {};
template<typename T>
struct Optional
{
Optional() noexcept : unused{} {}
~Optional() noexcept(noexcept(v.~T()))
{
if(constructed_successfully)
{
v.~T();
}
}
template<typename... Args>
auto emplace(Args &&... args) -> T &
{
if(constructed_successfully)
{
v.~T();
constructed_successfully = false;
}
T &r = *new (&v) T(std::forward<Args>(args)...);
constructed_successfully = true;
return r;
}
auto operator->() noexcept -> T *
{
return &v;
}
private:
union
{
T v;
[[no_unique_address]] Empty unused;
};
bool constructed_successfully = false;
};
The generated assembly is identical to with std::optional: https://gcc.godbolt.org/z/vzGz9E
Though, I would recommend using an existing library to supplement your lack of access to std::optional instead of rolling your own like I have done above - my version doesn't work for copying or moving.

Related

How to create a variable that will contain pointer to function regardless of arguments?

I want to make Dialog handler for my app that will contain pointer to method that will be invoked when user answer "yes" and pointer to method for "no" and the main problem that these methods can have various args or without it so i dont know how to declare this variable.
class Dialog
{
protected:
Dialog()
{
}
static Dialog* singleton;
public:
Dialog(Dialog &other) = delete;
void operator=(const Dialog &) = delete;
static Dialog *instance();
string question;
?? method_yes;
?? method_no;
static bool has_dialog();
static void clear();
};
Dialog* Dialog::singleton = nullptr;
Dialog* Dialog::instance()
{
if (singleton == nullptr) {
singleton = new Dialog();
}
return singleton;
}
bool Dialog::has_dialog()
{
return singleton != nullptr;
}
void Dialog::clear()
{
if (singleton)
{
delete singleton;
singleton = nullptr;
}
}
So there is my class for dialog with user, when i want to ask user something i do
auto yes = []()
{
ExitProcess(0);
};
Dialog::instance()->question = "Do you want to exit?";
Dialog::instance()->method_yes = yes;
And somewhere upper or whatever i have answer handling
if (Dialog::has_dialog())
// render question and buttons
// if pressed button yes
Dialog::instance()->method_yes();
Dialog::clear();
And what if for example i want to manage exit code so my lambda will be
auto yes = [](int code)
{
ExitProcess(code);
};
But then there is a new argument so i cant just use
void(*method_yes)();
for declaration
At the end of the day, C++ is a strongly typed language and you'll have to provide the set of expected possible arguments in your function signature.
Since you don't want that, there are some techniques to circumvent it so let's name a few:
The old (old old) void* trick from C. You declare your function pointer as
void (*fptr)(void* state);
and then you're free to interpret state however you wish in your fptr, e.g. if state==nullptr you can assume there are "no arguments". Note that this approach is not type safe and can cause a lot of headaches if users don't respect the agreed upon protocol.
You bundle all your state in your callable and your function pointer becomes something like std::function<void()>. This way you can write:
std::function<void()> fptr = [code]() { /* ... */ };
This is the nerfed version of the above, meaning your lambdas are now responsible for capturing the state you'd be passing to the function as arguments.
A pattern I'm using lately involves C++20 designated initializers like so:
struct Argument
{
std::optional<int> code;
std::optional<std::string> name;
std::optional<float> value;
};
void (*fptr)(Argument arg); // Argument is elastic, i.e.
// it can be formed as:
// {} -> no arguments
// {.code=1} -> 1 argument
// {.code=1, value=2.}-> 2 arguments
// etc
// Fields not mentioned default to
// nullopt, which means you have
// an easy way of telling them apart
int main ()
{
fptr = [](Argument arg) {
std::cout << arg.code.value_or(0) << std::endl;
std::cout << arg.name.value_or("no name") << std::endl;
std::cout << arg.value.value_or(42) << std::endl;
};
fptr({});
std::cout << "-------------\n";
fptr({.name="Garfield"});
std::cout << "-------------\n";
fptr({.code=3, .value=3.14});
std::cout << "-------------\n";
}
This is a type-safe alternative to (1). You declare the expected set of arguments in Argument but since they are optional you can call fptr({}) and mark everything as "non existent" (the no args case) or even initialize one or more arguments explicitly e.g. fptr({.code=3, .value=3.14}). Inside fptr you can inspect whether an optional variable is "filled" and this gives you the freedom to act accordingly (demo).
If all this still seems unattractive, I wrote a post some years ago on how to create overload sets out of lambdas. Essentially the technique allows you to write things like:
auto fptr = overload(
[]{ /*...*/ }, // A
[](int code) { /*...*/ }); // B
fptr(); // Calls A
fptr(22); // Calls B
Again this means that all possible solutions (sets of functions of different types) are known at compile time, but you dodge the pain of creating that set explicitly.
Finally I'd re-visit the design before resorting to such solutions, maybe a simpler path exists e.g. express the exit functions as a hierarchy and have a factory method to generate the active function at runtime or even reconsider why should an exit function be tweakable at runtime.

c++98 struct default to zero except one value

This is certainly related to a bunch of other questions which have been answered, but I have been unable to derive the answer for my specific case from them, largely because I'm not actually a programmer; I'm just an engineer who happens to have to write some code.
Here's the situation:
I have a bunch of variables I'd like to collect together, probably into a structure.
All but two I would like to initialize to zero; two specific variables (which don't happen to be the first two) need to be initialized to one.
The actual names are unique and meaningful enough that using a vector wouldn't be appropriate, plus there are some doubles in there too. I'm keeping my example below simple for clarity.
Because of the project I'm working on, I'm stuck with C++98, so even if C++11 has more elegant solutions, they won't work for me.
I am thinking something along these lines for the structure itself:
struct allFlags
{
int flagAA;
int flagAB;
int flagAC;
int flagAD;
int flagAE;
// ...
// there's about 100 variables total
// ...
int flagZZ;
};
I want to have all the flags initialized to 0 except for flagAD and flagAE, which should be 1.
So first of all, I am not sure if I should use typedef struct allFlags or struct allFlags. Next, I am not sure if I should be creating a constructor (which I think only would apply in the case of no typedef?) or making the defaults happens when I instantiate the structure. I have seen things like this (which would be put inside the struct definition):
allFlags() : flagAD(1), flagAE(1) { /*not sure of I'd need anything here*/ }
but I wouldn't want to have to list out all other ~98 variables by name individually in the constructor body to set them to zero. I have also seen things using memset which could potentially help, but I'm not sure the best way to do it.
And finally one additional related question is how to actually declare an instance of my structure (which results in the initial values I want). It looks like sometimes a struct is instantiated with the new keyword and sometimes is it treated more like a base data type, i.e. I have seen both of these in searching:
allFlags flagset1;
flagset2 = new allFlags;
I have also seen syntax which would be like this rather than using a constructor at all:
allFlags flagset3 = {}; // to zero all fields first
flagset3.flagAD = 1;
flagset3.flagAE = 1;
but I'd rather keep the instantiation as clean and simple as possible.
Please forgive the question. I have tried to do my homework before asking, but my C++ knowledge is mediocre at best and so some of the seemingly relevant answers I've found I either didn't fully understand or just raised more questions.
If you feel comfortable with using templates, you can use a class template to automate clean initialization of all member variables of allFlags.
// class template to help initialize members cleanly.
template <typename T>
struct flag
{
// Constructors
flag() : val(0) {}
flag(T const& v) : val(v) {}
// Automatic cast operators to T
operator T& () { return val; }
operator T const& () const { return val; }
// Comparison operators
bool operator==(flag const& rhs) const { return val == rhs.val; }
bool operator!=(flag const& rhs) const { return val != rhs.val; }
bool operator<(flag const& rhs) const { return val < rhs.val; }
T val;
};
typedef flag<int> IntFlag;
typedef flag<double> DoubleFlag;
struct allFlags
{
// Initialize all flags bug flagAD to zero.
allFlags() : flagAD(1) {}
IntFlag flagAA;
IntFlag flagAB;
IntFlag flagAC;
IntFlag flagAD;
IntFlag flagAE;
IntFlag flagZZ;
};
#include <iostream>
int main()
{
allFlags f;
std::cout << f.flagAA << " " << f.flagAD << std::endl;
}
Output:
0 1
You answered your own question quite well:
allFlags flagset3 = {}; // to zero all fields first
flagset3.flagAD = 1;
flagset3.flagAE = 1;
It is clean, and very clear about your intentions. Later, when someone else has to read your code they will understand exactly what you are trying to do.
It is similar to what you see in device driver programming:
registerX = 0 | 1 << BIT2 | 1 << BIT3;

Class properties not holding values

im working in a text-based RPG game, but when I'm setting the values to X variable, when I access that propertie again, it is in its default value, am I doing something wrong?
class Game
{
private:
bool podeAndar;
bool estaBatalhando;
Jogador _jogador;
Mapa _mapa;
public:
Game() { }
Game(Jogador _j){
_jogador = Jogador(_j.getNome());
_mapa.LoadMapa();
podeAndar = true;
estaBatalhando = false;
}
~Game(void)
{
}
Jogador getJogador() {
return _jogador;
}
void setJogador(Jogador v) {
_jogador = v;
}
}
My "Player" class
#pragma once
#include "Criatura.h"
#include <string>
class Jogador :
public Criatura
{
private:
int _cap;
public:
Jogador(std::string nome)
{
setNome(nome);
setCap(150);
}
Jogador() { }
~Jogador(void)
{
}
int getCap(){
return _cap;
}
void setCap(int v){
_cap = v;
}
}
Them my "Main" - when I set the value, when I'm following it in the debugger, it sets the value correctly, but when I access the game.getJogador().getCap() again, it has the default value 150.
int _tmain(int argc, _TCHAR* argv[])
{
Jogador _player = Jogador("Kyore");
Game game = Game(_player);
while(true){
std::cout << game.getJogador().getCap(); //print 150
game.getJogador().setCap(100); //set cap to 100
std::cout << game.getJogador().getCap(); //print 150 again
break;
}
}
In Game class, change this
Jogador getJogador() {
return _jogador;
}
to
Jogador& getJogador() {
return _jogador;
}
And add one more method only to read:
const Jogador& getJogador()const {
return _jogador;
}
Update for the questions asked in the comment
To fix your specific issue of value remaining as 150 inspite of setting a new value, converting the return type to reference is enough.
Why returning reference works?
Because, whenever your original version of getJogador() is called, a copy of the object is
created. Even though you are changing its value, you are actually
changing the value of the temporary object created, not the original
one.
So as your intention is to modify the original object, we need
to access the original one, not its temporary copy. Reference is
the better mechanism in such cases (pointer being the other mechanism, but less safer than reference)
Now about why I suggested the new over load of a const member
function, returning a const reference: this is to highlight to you that it is possible to still get the object without changing its internal state unintentionally. Your sample code does not differentiate between the two getJogador() functions.
So to understand, add these two functions to your Game class:
void DontManipulate()const { std::cout<<getJogador().getCap(); }
void Manipulate() { std::cout<<getJogador().getCap(); }
See the compiler error(s) that you get: - it should throw light on the differences.
Additionally, if you std::cout some message in both the getJogador() functions, you should be able to figure out the differences.
The problem is in your getJogador() method.
In C++, objects can be passed "by value" - which is where the program (usually) copies the object's raw data into a new location, whereas in C# and Java objects are always passed by reference (not counting C#'s structs which are passed by-value similar to C++). C++ will use the "copy constructor" to perform this copy. C++ will create the copy constructor if it isn't explicitly defined in your code, the signature has the form ClassName(ClassName& other);, the default (non-explicit) copy-constructor performs a shallow, member-wise copy operation.
In your case, your getJogador method is returning a copy of your Jogador instance field's data.
Change the method to return a reference or a pointer, like so:
Jogador& getJogador() const {
return _jogador;
}
or
Jogador* getJogador() const {
return &_jogador;
}
The const modifier informs the compiler that this method is not intended to modify the state of your Game class, so the compiler might perform certain optimizations as well as prevent successful compilation if the method does attempt to modify state.

RAII way to choose between two constructors

I have a class that holds a large table of data, with a constructor that takes all of the parameters needed to calculate that data. However, it takes a long time to run, so I've added a constructor that takes a stream, and reads the data in from that stream. I'm having trouble coming up with a RAII way of designing this class though, since I have two constructors, and at run time I need to choose between them. This is what I've come up with:
std::string filename; // Populated by command line arguments
DataTable table; // Empty constructor, no resource acquisition or initialization
if( filename.empty() ) {
table = DataTable(/*various parameters*/);
} else {
std::ifstream filestream(filename);
table = DataTable(filestream); // Reads from file
}
That looks pretty fragile to me. The default constructor will leave the object in a valid state, but a useless one. The only use of it is to create a "temporary" object in the outer scope, to be assigned to in one of the branches of the if statement. Additionally, there's a flag "inited" behind the scenes to manage if the object was default-constructed or fully initialized. Is there a better way to design this class?
Maybe like this:
DataTable foo = filename.empty()
? DataTable(x, y, z)
: DataTable(std::ifstream(filename));
Move the file test code that decides which way to init into the ctor, move the ctors into two private init functions, call one of these from the ctor or throw an exception if everything fails.
Some thoughts:
Get rid of the "inited" flag.
Get rid of the default constructor if it can't sensibly construct the object
use this kind of construct to get you a DataTable:
DataTable get_me_my_data_fool(ParameterTypes... params, const string& filename = "")
{
if(!filename.empty())
return DataTable(std::ifstream(filename)); // check if file exists!
else
return DataTable(params...);
}
Actually, now that I think about it, it would be better to just put this logic into the DataTable constructor.
If the class supports copy, then Kerrek SB's solution is the way
to go. From what you say, however, copying is expensive. In
that case, and you can use C++11, you might try adding a move
constructor, in order to avoid the deep copy. Otherwise, you're
probably stuck allocating dynamically:
std::auto_ptr<DataTable> fooPtr( filename.empty()
? new DataTable( x, y z )
: new DataTable( filename ) );
DataTable& foo = *fooPtr;
Here's another idea for completeness sake:
template<typename T>
class uninitialised
{
public:
~uninitialised()
{
if (alive_) {
operator T&().~T();
}
}
template<typename... Ts>
void create(Ts&&... args)
{
assert(!alive_ && "create must only be called once");
void* const p = obj_;
::new(p) T(std::forward<Ts>(args)...);
alive_ = true;
}
operator T&()
{
assert(alive_ && "T has not been created yet");
return *reinterpret_cast<T*>(obj_);
}
private:
bool alive_ = false;
alignas(T) unsigned char obj_[sizeof(T)];
};
// ...
std::string filename;
uninitialised<DataTable> table;
if (filename.empty()) {
table.create(/* various parameters */);
} else {
std::ifstream filestream(filename);
table.create(filestream);
}
DataTable& tbl = table;

Returning a "NULL reference" in C++?

In dynamically typed languages like JavaScript or PHP, I often do functions such as:
function getSomething(name) {
if (content_[name]) return content_[name];
return null; // doesn't exist
}
I return an object if it exists or null if not.
What would be the equivalent in C++ using references? Is there any recommended pattern in general? I saw some frameworks having an isNull() method for this purpose:
SomeResource SomeClass::getSomething(std::string name) {
if (content_.find(name) != content_.end()) return content_[name];
SomeResource output; // Create a "null" resource
return output;
}
Then the caller would check the resource that way:
SomeResource r = obj.getSomething("something");
if (!r.isNull()) {
// OK
} else {
// NOT OK
}
However, having to implement this kind of magic method for each class seems heavy. Also it doesn't seem obvious when the internal state of the object should be set from "null" to "not null".
Is there any alternative to this pattern? I already know it can be done using pointers, but I am wondering how/if it can be done with references. Or should I give up on returning "null" objects in C++ and use some C++-specific pattern? Any suggestion on the proper way to do that would be appreciated.
You cannot do this during references, as they should never be NULL. There are basically three options, one using a pointer, the others using value semantics.
With a pointer (note: this requires that the resource doesn't get destructed while the caller has a pointer to it; also make sure the caller knows it doesn't need to delete the object):
SomeResource* SomeClass::getSomething(std::string name) {
std::map<std::string, SomeResource>::iterator it = content_.find(name);
if (it != content_.end())
return &(*it);
return NULL;
}
Using std::pair with a bool to indicate if the item is valid or not (note: requires that SomeResource has an appropriate default constructor and is not expensive to construct):
std::pair<SomeResource, bool> SomeClass::getSomething(std::string name) {
std::map<std::string, SomeResource>::iterator it = content_.find(name);
if (it != content_.end())
return std::make_pair(*it, true);
return std::make_pair(SomeResource(), false);
}
Using boost::optional:
boost::optional<SomeResource> SomeClass::getSomething(std::string name) {
std::map<std::string, SomeResource>::iterator it = content_.find(name);
if (it != content_.end())
return *it;
return boost::optional<SomeResource>();
}
If you want value semantics and have the ability to use Boost, I'd recommend option three. The primary advantage of boost::optional over std::pair is that an unitialized boost::optional value doesn't construct the type its encapsulating. This means it works for types that have no default constructor and saves time/memory for types with a non-trivial default constructor.
I also modified your example so you're not searching the map twice (by reusing the iterator).
Why "besides using pointers"? Using pointers is the way you do it in C++. Unless you define some "optional" type which has something like the isNull() function you mentioned. (or use an existing one, like boost::optional)
References are designed, and guaranteed, to never be null. Asking "so how do I make them null" is nonsensical. You use pointers when you need a "nullable reference".
One nice and relatively non-intrusive approach, which avoids the problem if implementing special methods for all types, is that used with boost.optional. It is essentially a template wrapper which allows you to check whether the value held is "valid" or not.
BTW I think this is well explained in the docs, but beware of boost::optional of bool, this is a construction which is hard to interpret.
Edit: The question asks about "NULL reference", but the code snippet has a function that returns by value. If that function indeed returned a reference:
const someResource& getSomething(const std::string& name) const ; // and possibly non-const version
then the function would only make sense if the someResource being referred to had a lifetime at least as long as that of the object returning the reference (otherwise you woul dhave a dangling reference). In this case, it seems perfectly fine to return a pointer:
const someResource* getSomething(const std::string& name) const; // and possibly non-const version
but you have to make it absolutely clear that the caller does not take ownership of the pointer and should not attempt to delete it.
I can think of a few ways to handle this:
As others suggested, use boost::optional
Make the object have a state that indicates it is not valid (Yuk!)
Use pointer instead of reference
Have a special instance of the class that is the null object
Throw an exception to indicate failure (not always applicable)
unlike Java and C# in C++ reference object can't be null.
so I would advice 2 methods I use in this case.
1 - instead of reference use a type which have a null such as std::shared_ptr
2 - get the reference as a out-parameter and return Boolean for success.
bool SomeClass::getSomething(std::string name, SomeResource& outParam) {
if (content_.find(name) != content_.end())
{
outParam = content_[name];
return true;
}
return false;
}
This code below demonstrates how to return "invalid" references; it is just a different way of using pointers (the conventional method).
Not recommended that you use this in code that will be used by others, since the expectation is that functions that return references always return valid references.
#include <iostream>
#include <cstddef>
#define Nothing(Type) *(Type*)nullptr
//#define Nothing(Type) *(Type*)0
struct A { int i; };
struct B
{
A a[5];
B() { for (int i=0;i<5;i++) a[i].i=i+1; }
A& GetA(int n)
{
if ((n>=0)&&(n<5)) return a[n];
else return Nothing(A);
}
};
int main()
{
B b;
for (int i=3;i<7;i++)
{
A &ra=b.GetA(i);
if (!&ra) std::cout << i << ": ra=nothing\n";
else std::cout << i << ": ra=" << ra.i << "\n";
}
return 0;
}
The macro Nothing(Type) returns a value, in this case that represented by nullptr - you can as well use 0, to which the reference's address is set. This address can now be checked as-if you have been using pointers.
From C++17 on, you can use the native std::optional (here) in the following way:
std::optional<SomeResource> SomeClass::getSomething(std::string name) {
if (content_.find(name) != content_.end()) return content_[name];
return std::nullopt;
}
Here are a couple of ideas:
Alternative 1:
class Nullable
{
private:
bool m_bIsNull;
protected:
Nullable(bool bIsNull) : m_bIsNull(bIsNull) {}
void setNull(bool bIsNull) { m_bIsNull = bIsNull; }
public:
bool isNull();
};
class SomeResource : public Nullable
{
public:
SomeResource() : Nullable(true) {}
SomeResource(...) : Nullable(false) { ... }
...
};
Alternative 2:
template<class T>
struct Nullable<T>
{
Nullable(const T& value_) : value(value_), isNull(false) {}
Nullable() : isNull(true) {}
T value;
bool isNull;
};
Yet another option - one that I have used from time to time for when you don't really want a "null" object returned but instead an "empty/invalid" object will do:
// List of things
std::vector<some_struct> list_of_things;
// An emtpy / invalid instance of some_struct
some_struct empty_struct{"invalid"};
const some_struct &get_thing(int index)
{
// If the index is valid then return the ref to the item index'ed
if (index <= list_of_things.size())
{
return list_of_things[index];
}
// Index is out of range, return a reference to the invalid/empty instance
return empty_struct; // doesn't exist
}
Its quite simple and (depending on what you are doing with it at the other end) can avoid the need to do null pointer checks on the other side. For example if you are generating some lists of thing, e.g:
for (const auto &sub_item : get_thing(2).sub_list())
{
// If the returned item from get_thing is the empty one then the sub list will
// be empty - no need to bother with nullptr checks etc... (in this case)
}