Related
I am learning how c++ is compiled into assembly and I found how exceptions works under the hood very interesting. If its okay to have more then one execution paths for exceptions why not for normal functions.
For example, lets say you have a function that can return a pointer to class A or something derived from A. The way your supposed to do it is with RTTI.
But why not, instead, have the called function, after computing the return value, jump back to the caller function into the specific location that matchs up with the return type. Like how exceptions, the execution flow can go normal or, if it throws, it lands in one of your catch handlers.
Here is my code:
class A
{
public:
virtual int GetValue() { return 0; }
};
class B : public A
{
public:
int VarB;
int GetValue() override { return VarB; }
};
class C : public A
{
public:
int VarC;
int GetValue() override { return VarC; }
};
A* Foo(int i)
{
if(i == 1) return new B;
if(i == 2)return new C;
return new A;
}
void main()
{
A* a = Foo(2);
if(B* b = dynamic_cast<B*>(a))
{
b->VarB = 1;
}
else if(C* c = dynamic_cast<C*>(a)) // Line 36
{
c->VarC = 2;
}
else
{
assert(a->GetValue() == 0);
}
}
So instead of doing it with RTTI and dynamic_cast checks, why not have the Foo function just jump to the appropriate location in main. So in this case Foo returns a pointer to C, Foo should instead jump to line 36 directly.
Whats wrong with this? Why aren't people doing this? Is there a performance reason? I would think this would be cheaper then RTTI.
Or is this just a language limitation, regardless if its a good idea or not?
First of all, there are million different ways of defining the language. C++ is defined as it is defined. Nice or not really does not matter. If you want to improve the language, you are free to write a proposal to C++ committee. They will review it and maybe include in future standards. Sometimes this happens.
Second, although exceptions are dispatched under the hood, there are no strong reasons to think that this is more efficient comparing your handwritten code that uses RTTI. Exception dispatch still requires CPU cycles. There is no miracle there. The real difference is that for using RTTI you need to write the code yourself, while the exception dispatch code is generated for you by compiler.
You may want to call you function 10000 times and find out what will run faster: RTTI based code or exception dispatch.
Im studying programming and I just started learning about set and get functions.
My questions is if it is common practise to use set-functions with a return value?
Like when the set-function performs validation i would like it to return true if the incoming value passes the validation.
Googled it and looked throug my course material and found nothing, only void set-functions everywhere!! :)
Thx
In some cases you may want to return the reference to *this from setter methods to implement fluent interface. A simple example:
class C {
int x,y;
public:
C& setX(int value) { x = value; return *this; }
C& setY(int value) { y = value; return *this; }
};
such class may be then used in the following way:
C c;
c.setX(1).setY(2);
The core motivation for getter/setter is value validation / sanity check values so returning a bool is a common way to make known if operation occurred successfully:
bool Class::setSomething(int a)
{
if (is_ok(a))
{
// set...
return true;
}
return false;
}
This is
quick/easy to implement
has smaller footprint than exception handling (although this is negligible these days)
but
it can't pass back any extra information to the caller (why did it break?)
is easier to ignore compared to exceptions
Depending on what the setter is doing.
My set functions which only assign values to class members are void
void Class::setParameter(Parameter param)
{
m_parameter = param;
}
if the setter is doing more than this, I can envisage returning a boolean.
I like the feature in Python that can return None when it doesn't find the correct return value. For example:
def get(self, key):
if key in self.db:
return self.db[key]
return None
I need to implement the same feature in C++. I think about some possibilities.
Return true/false, when true get the value from reference or pointer
bool get(string key, int& result)
{
if (in(key, db)) {
result = db[key];
return true;
}
return false;
}
Throw an error for notifying None case
int get(string key) throw (int)
{
if (in(key, db)) {
result = db[key];
return result;
}
throw 0;
}
try {
....
}
catch (int n)
{
cout << "None";
}
Use pair
pair<bool, int> getp(int i)
{
if (...) {
return pair<bool, int>(true, 10);
}
return pair<bool,int>(false, 20);
}
pair<bool, int> res = getp(10);
if (res.first) {
cout << res.second;
}
Which one is normally used in C++? Are there any other ways to do it in C++?
The normal C++ way to do this (note: C++ is not Python) is to return iterators from such functions and return end() when the item can't be found.
If you wish to use non-iterator return values however, use boost::optional and return boost::none when you would return Python's None.
Definitely don't use throw unless you expect to never have the error case during normal execution.
I achieved the good/bad return value using a small custom Checked templated class.
My actual class was a little more comprehensive, including assignment operators, error reason strings and specialisations for reference types, et cetera, which is why I didn't use boost::optional<T>. I could publish the full class if there is interest.
The general gist of the class is this:
static const class Bad {} None;
template<typename ValueType>
class Checked
{
public:
// Constructor for good value.
Checked(ValueType x)
: value(x), valid(true)
{}
// Constructor for bad value.
Checked(Bad)
: value(), valid(false)
{}
operator ValueType(void) const
{
if (!valid)
;//assert or throw...
return value;
}
ValueType value;
bool valid;
};
This can be used like so:
Checked<int> Divide(int numerator, int denominator)
{
if (denominator == 0)
return Bad(); // or None;
return numerator / denominator; // Automatically uses the "good value" constructor
}
or:
Checked<int> result = Divide(4, 5);
if (result.valid)
std::cout << result; // or result.value
else
std::cout << "Bad!";
This approach is often more efficient than the reference approach because of return value optimisation.
I think different projects in C++ use different standards, but Return true/false you mentioned could be the most common way in C++, although some people prefer to return false on success while the others return true on success. In other cases, if the value you would like to get is a pointer, then returning null is another common way in C++.
For example, if you're working on Microsoft related projects, then the most common way is to return HRESULT, which is a return type introduced by Microsoft.
In linux, functions usually return 0 on success, and non-zero value indicates error code.
(you may find this discussion helpful).
I would say that those three methods are all very common in C++.
It goes without saying that if the return type already can have some sort of "invalid" or "zombie" state (e.g., like a NULL pointer or a NaN number), then that might just be the easiest thing to use.
The "take output-parameter by reference and return an error-code" is the more traditional C-style way of doing things, which is, of course, very common. The tradition is to return 0 on success and some error-code on failure (any non-zero value).
The "throw an exception if you can't return a value" generally makes sense if you adopt exceptions in your code. This is very common, but not universally accepted (not everyone likes or uses exceptions for the same purposes).
Those first two options are in a never-ending feud (i.e., error-codes vs. exceptions), and it really depends on which side you pick. So, I would refer you to that debate (which is too subjective for StackOverflow, of course).
The "return a pair of bool and value" is, I would say, less common, but still I've seen this many times. With the adoption of tuples (boost::tuple or std::tuple (C++11)) and with the use of tiers (boost::tie or std::tie (C++11)), the whole idea of returning multiple values from a function (like many languages allow) is ever more attractive and used in practice.
Among other options, you have boost::optional<T>, whose name is pretty self-explanatory (basically, the third option (pair) wrapped in a prettier package). And you might also have Alexandrescu's Expected template, which gives you a hybrid of all three options such that you get a return value bundled with a flag to know if it is valid or not, and bundled with an exception describing why it couldn't produce the value, which would be automatically thrown if you attempt to read the invalid value. However, the template requires C++11 features to work.
When returning pointer, I can use reinterpret_cast for NULL return.
class A
{
};
A* a(int i)
{
if (i == 0) return new A();
return reinterpret_cast<A*>(NULL);
}
int main(int argc, char *argv[]) {
A* result = a(1); // result is NULL
if (result == NULL) {
cout << "NULL returned";
}
result = a(0);
if (result != NULL) {
cout << "NON NULL returned";
}
}
It is common knowledge that built-in enums in C++ are not typesafe.
I was wondering which classes implementing typesafe enums are used out there...
I myself use the following "bicycle", but it is somewhat verbose and limited:
typesafeenum.h:
struct TypesafeEnum
{
// Construction:
public:
TypesafeEnum(): id (next_id++), name("") {}
TypesafeEnum(const std::string& n): id(next_id++), name(n) {}
// Operations:
public:
bool operator == (const TypesafeEnum& right) const;
bool operator != (const TypesafeEnum& right) const;
bool operator < (const TypesafeEnum& right) const;
std::string to_string() const { return name; }
// Implementation:
private:
static int next_id;
int id;
std::string name;
};
typesafeenum.cpp:
int TypesafeEnum::next_id = 1;
bool TypesafeEnum::operator== (const TypesafeEnum& right) const
{ return id == right.id; }
bool TypesafeEnum::operator!= (const TypesafeEnum& right) const
{ return !operator== (right); }
bool TypesafeEnum::operator< (const TypesafeEnum& right) const
{ return id < right.id; }
Usage:
class Dialog
{
...
struct Result: public TypesafeEnum
{
static const Result CANCEL("Cancel");
static const Result OK("Ok");
};
Result doModal();
...
};
const Dialog::Result Dialog::Result::OK;
const Dialog::Result Dialog::Result::CANCEL;
Addition:
I think I should have been more specific about the requirements. I'll try to summarize them:
Priority 1: Setting an enum variable to an invalid value should be impossible (a compile-time error) with no exceptions.
Priority 2: Converting an enum value to/from an int should be possible with a single explicit function/method call.
Priority 3: As compact, elegant and convenient declaration and usage as possible
Priority 4: Converting enum values to and from strings.
Priority 5: (Nice to have) Possibility to iterate over enum values.
I'm currently playing around with the Boost.Enum proposal from the Boost Vault (filename enum_rev4.6.zip). Although it was never officially submitted for inclusion into Boost, it's useable as-is. (Documentation is lacking but is made up for by clear source code and good tests.)
Boost.Enum lets you declare an enum like this:
BOOST_ENUM_VALUES(Level, const char*,
(Abort)("unrecoverable problem")
(Error)("recoverable problem")
(Alert)("unexpected behavior")
(Info) ("expected behavior")
(Trace)("normal flow of execution")
(Debug)("detailed object state listings")
)
And have it automatically expand to this:
class Level : public boost::detail::enum_base<Level, string>
{
public:
enum domain
{
Abort,
Error,
Alert,
Info,
Trace,
Debug,
};
BOOST_STATIC_CONSTANT(index_type, size = 6);
Level() {}
Level(domain index) : boost::detail::enum_base<Level, string>(index) {}
typedef boost::optional<Level> optional;
static optional get_by_name(const char* str)
{
if(strcmp(str, "Abort") == 0) return optional(Abort);
if(strcmp(str, "Error") == 0) return optional(Error);
if(strcmp(str, "Alert") == 0) return optional(Alert);
if(strcmp(str, "Info") == 0) return optional(Info);
if(strcmp(str, "Trace") == 0) return optional(Trace);
if(strcmp(str, "Debug") == 0) return optional(Debug);
return optional();
}
private:
friend class boost::detail::enum_base<Level, string>;
static const char* names(domain index)
{
switch(index)
{
case Abort: return "Abort";
case Error: return "Error";
case Alert: return "Alert";
case Info: return "Info";
case Trace: return "Trace";
case Debug: return "Debug";
default: return NULL;
}
}
typedef boost::optional<value_type> optional_value;
static optional_value values(domain index)
{
switch(index)
{
case Abort: return optional_value("unrecoverable problem");
case Error: return optional_value("recoverable problem");
case Alert: return optional_value("unexpected behavior");
case Info: return optional_value("expected behavior");
case Trace: return optional_value("normal flow of execution");
case Debug: return optional_value("detailed object state listings");
default: return optional_value();
}
}
};
It satisfies all five of the priorities which you list.
A nice compromise method is this:
struct Flintstones {
enum E {
Fred,
Barney,
Wilma
};
};
Flintstones::E fred = Flintstones::Fred;
Flintstones::E barney = Flintstones::Barney;
It's not typesafe in the same sense that your version is, but the usage is nicer than standard enums, and you can still take advantage of integer conversion when you need it.
I use C++0x typesafe enums. I use some helper template/macros that provide the to/from string functionality.
enum class Result { Ok, Cancel};
I don't. Way too much overhead for little benefit. Also, being able to caste enumerations to different data types for serialization is a very handy tool. I have never seen an instance where a "Type safe" enumeration would be worth the overhead and complexity where C++ offers a good enough implementation already.
My take is that you're inventing a problem and then fitting a solution onto it. I see no need to do an elaborate framework for an enumeration of values. If you are dedicated to having your values only be members of a certain set, you could hack up a variant of a unique set datatype.
I'm personally using an adapted version of the typesafe enum idiom. It doesn't provide all the five "requirements" that you've stated in your edit, but I strongly disagree with some of them anyway. For example, I don't see how Prio#4 (conversion of values to strings) has anything to do with type safety. Most of the time string representation of individual values should be separate from the definition of the type anyway (think i18n for a simple reason why). Prio#5 (iteratio, which is optional) is one of the nicest things I'd like to see naturally happening in enums, so I felt sad that it appears as "optional" in your request, but it seems it is better addressed via a separate iteration system such as begin/end functions or an enum_iterator, which makes them work seamlessly with STL and C++11 foreach.
OTOH this simple idiom nicely provides Prio#3 Prio#1 thanks to the fact that it mostly only wraps enums with more type information. Not to mention it is a very simple solution that for the most part doesn't require any external dependency headers, so it's pretty easy to carry around. It also has the advantage of making enumerations scoped a-la-C++11:
// This doesn't compile, and if it did it wouldn't work anyway
enum colors { salmon, .... };
enum fishes { salmon, .... };
// This, however, works seamlessly.
struct colors_def { enum type { salmon, .... }; };
struct fishes_def { enum type { salmon, .... }; };
typedef typesafe_enum<colors_def> colors;
typedef typesafe_enum<fishes_def> fishes;
The only "hole" that solution provides is that it doesn't address the fact that it doesn't prevent enums of different types (or an enum and an int) from being directly compared, because when you use values directly you force the implicit conversion to int:
if (colors::salmon == fishes::salmon) { .../* Ooops! */... }
But so far I've found such problems can be solved by simply offering a better comparison to the compiler - for example, explicitly providing an operator that compares any two different enum types, then forcing it to fail:
// I'm using backports of C++11 utilities like static_assert and enable_if
template <typename Enum1, typename Enum2>
typename enable_if< (is_enum<Enum1>::value && is_enum<Enum2>::value) && (false == is_same<Enum1,Enum2>::value) , bool >
::type operator== (Enum1, Enum2) {
static_assert (false, "Comparing enumerations of different types!");
}
Though it doesn't seem to break code so far, and it does to explicitly deal with the specific problem without doing something else, I'm not sure it such thing is a thing one "should" do (I suspect it will interfere with enums already taking part in conversion operators declared elsewhere; I'd gladly receive commentary about this).
Combining this with the above typesafe idiom gives something that is relatively close to C++11 enum class in humanibility (readability and maintainability) without having to do anything too obscure. And I have to admit it was fun to do, I had never thought to actually ask the compiler if I was dealing with enums or not...
I think the Java enum would be a good model to follow. Essentially, the Java form would look like this:
public enum Result {
OK("OK"), CANCEL("Cancel");
private final String name;
Result(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
What's interesting about the Java approach is that OK and CANCEL are immutable, singleton instances of Result (with the methods that you see). You cannot create any further instances of Result. Since they're singletons, you can compare by pointer/reference---very handy. :-)
ETA: In Java, instead of doing bitmasks by hand, instead you use an EnumSet to specify a bit set (it implements the Set interface, and works like sets---but implemented using bitmasks). Much more readable than hand-written bitmask manipulation!
I gave an answer to this here, on a different topic. It's a different style of approach which allows most of the same functionality without requiring modification to the original enum definition (and consequently allowing usage in cases where you don't define the enum). It also allows runtime range checking.
The downside of my approach is that it doesn't programmatically enforce the coupling between the enum and the helper class, so they have to be updated in parallel. It works for me, but YMMV.
I am currently writing my own typesafe enum library at https://bitbucket.org/chopsii/typesafe-enums
I am not the most experienced C++ developer ever, but I am writing this due to the shortcomings of the BOOST vault enums.
Feel free to check it out and use them yourself, but they have some (hopefully minor) usability issues, and are probably not at all cross-platform.
Please contribute if you want to. This is my first open source undertaking.
Use boost::variant!
After trying a lot of the above ideas and finding them lacking I hit upon this simple approach:
#include <iostream>
#include <boost/variant.hpp>
struct A_t {};
static const A_t A = A_t();
template <typename T>
bool isA(const T & x) { if(boost::get<A_t>(&x)) return true; return false; }
struct B_t {};
static const B_t B = B_t();
template <typename T>
bool isB(const T & x) { if(boost::get<B_t>(&x)) return true; return false; }
struct C_t {};
static const C_t C = C_t();
template <typename T>
bool isC(const T & x) { if(boost::get<C_t>(&x)) return true; return false; }
typedef boost::variant<A_t, B_t> AB;
typedef boost::variant<B_t, C_t> BC;
void ab(const AB & e)
{
if(isA(e))
std::cerr << "A!" << std::endl;
if(isB(e))
std::cerr << "B!" << std::endl;
// ERROR:
// if(isC(e))
// std::cerr << "C!" << std::endl;
// ERROR:
// if(e == 0)
// std::cerr << "B!" << std::endl;
}
void bc(const BC & e)
{
// ERROR:
// if(isA(e))
// std::cerr << "A!" << std::endl;
if(isB(e))
std::cerr << "B!" << std::endl;
if(isC(e))
std::cerr << "C!" << std::endl;
}
int main() {
AB a;
a = A;
AB b;
b = B;
ab(a);
ab(b);
ab(A);
ab(B);
// ab(C); // ERROR
// bc(A); // ERROR
bc(B);
bc(C);
}
You can probably come up with a macro to generate the boilerplate. (Let me know if you do.)
Unlike other approaches this one is actually type-safe and works with old C++. You can even make cool types like boost::variant<int, A_t, B_t, boost::none>, for example, to represent a value that could be A, B, an integer or nothing which is almost Haskell98 levels of type safety.
Downsides to be aware of:
at-least with old boost -- I'm on a system with boost 1.33 -- you are limited to 20 items in your variant; there is a work-around however
affects compile time
insane error messages -- but that's C++ for you
Update
Here, for your convenience is your typesafe-enum "library". Paste this header:
#ifndef _TYPESAFE_ENUMS_H
#define _TYPESAFE_ENUMS_H
#include <string>
#include <boost/variant.hpp>
#define ITEM(NAME, VAL) \
struct NAME##_t { \
std::string toStr() const { return std::string( #NAME ); } \
int toInt() const { return VAL; } \
}; \
static const NAME##_t NAME = NAME##_t(); \
template <typename T> \
bool is##NAME(const T & x) { if(boost::get<NAME##_t>(&x)) return true; return false; } \
class toStr_visitor: public boost::static_visitor<std::string> {
public:
template<typename T>
std::string operator()(const T & a) const {
return a.toStr();
}
};
template<BOOST_VARIANT_ENUM_PARAMS(typename T)>
inline static
std::string toStr(const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & a) {
return boost::apply_visitor(toStr_visitor(), a);
}
class toInt_visitor: public boost::static_visitor<int> {
public:
template<typename T>
int operator()(const T & a) const {
return a.toInt();
}
};
template<BOOST_VARIANT_ENUM_PARAMS(typename T)>
inline static
int toInt(const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & a) {
return boost::apply_visitor(toInt_visitor(), a);
}
#define ENUM(...) \
typedef boost::variant<__VA_ARGS__>
#endif
And use it like:
ITEM(A, 0);
ITEM(B, 1);
ITEM(C, 2);
ENUM(A_t, B_t) AB;
ENUM(B_t, C_t) BC;
Notice you have to say A_t instead of A in the ENUM macro which destroys some of the magic. Oh well. Also, notice there's now a toStr function and a toInt function to meet OPs requirement of simple conversion to strings and ints. The requirement I can't figure out is a way to iterate over the items. Let me know if you know how to write such a thing.
Not sure if this post is too late, but there's an article on GameDev.net which satisfies all but the 5th point (ability to iterate over enumerators):
http://www.gamedev.net/reference/snippets/features/cppstringizing/
The method described by the article allows string conversion support for existing enumerations without changing their code. If you only want support for new enumerations though, I'd go with Boost.Enum (mentioned above).
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)
}