Reputation: 13125
I have a getter object that returns an object of type Type, defined as follows:
typedef boost::variant<int, std::string> Empty;
It is often the case that I will have neither an int nor a string to return and will have to instead return an empty state. How do you think I return this state?
a) typedef an Empty type and add it to the variant: boost::variant<int, std::string, Empty>
.
b) return Type()
c) Cast an exception
d) return a boost::shared_ptr, which points to NULL in the case of empty.
Upvotes: 4
Views: 1140
Reputation: 473252
The correct answer is to use boost::blank
for a variant that can have nothing in it. Thus, your variant typedef looks like this:
typedef boost::variant<boost::blank, int, std::string> Empty;
blank
is designed specifically for this, and variant
has special code based on it. By using it, you get a no-memory-allocation guarantee on copying (if the members don't allocate on copy). So that's good.
Since your variant can be "empty", it is important that all of your processing visitors can handle it. It's often more convenient to add an additional visitor pathway than to have a number of conditionals based on an optional
or something. The different code pathways will be localized to the visitors, which often makes more sense than an optional<variant>
.
Upvotes: 9
Reputation: 33655
Wrap it in a boost::optional
, this has a simple test (convertible to boolean) to determine if there is a valid value assigned - then you don't need to pollute your variant with an "empty" state. e.g.
boost::optional<boost::variant<... > > some_func()
{
:
}
Remember to use in place construction in your function when you actually need to return something.
Upvotes: 3
Reputation: 2139
It is a common approach if there is a possibility that the method can't return an object - make the method returning a bool:
bool get_value(Type& type) {
if ( /*check variant emptyness*/) // one can use this - http://stackoverflow.com/a/7668530/670719
return false;
// else assign type
}
Comments on your solutions:
a) if you will return Empty you will still have to do a check after a method call. So why adding more types if there is a built-in bool already.
b) Type() can have the same value as a legal variable
c) exception is for something exceptional, but from your description "it is often"
d) your problem is that you can't use Type and at the same time can't return boost::variant, so adding one more type with additional ownership issues brings more questions on what is going on without solving initial issue of clean interface.
Upvotes: 1