Reputation: 59
I have a question about boost::variant
and correct usage of it in methods. For instance, I have classes like Stuff
and User
and I have function (pseudo code):
boost::variant<User*, Stuff*> HashTable::getPersonByKey(string login, string password, string list_type)
{
int index = hash(login, password);
boost::variant<User*, Stuff*> temp_u, temp_s;
if (list_type == "User")
{
if (user_array[index].getPerson(login, password))
{
temp_u = user_array[index].getPerson(login, password);
//returns User*
//maybe something like variant<User* , Stuff*> (temp_u);
return VARIANT
}
}
else if (list_type == "Stuff")
{
if (user_array[index].getPerson(login, password))
{
temp_s = stuff_array[index].getPerson(login, password);
//returns Stuff*
//maybe something like variant<User* , Stuff*> (temp_s);
return VARIANT
}
}
return boost::variant<User*, Stuff*>();
}
How is the return supposed to be?
Can I make something even more complex like ...
boost::variant<boost::variant<User*, Stuff*>, boost::variant<User*, Stuff*>>getPerson()
{
boost::variant<boost::variant<User*, Stuff*>, boost::variant<User*, Stuff*>> temp_user1, temp_stuff1 ,
temp_user2 , temp_stuff2;
temp_u = user_array[index].getPerson(login, password);
return variant<variant <User* , Stuff*> ,variant <User* , Stuff*>> (temp_user1);
}
Should I somehow explicitly show to which variant temp_person
belongs to?
Will it be a problem to get objects out of this?
Upvotes: 1
Views: 2049
Reputation: 4905
You can think about boost::variant
as a improved C++ union
.
For example, as a union
, boost::variant<User*, Stuff*>
can store either a pointer to User
or a pointer to Stuff
but unlike a union
, you can check which type is stored.
In your example you declare:
boost::variant<User*, Stuff*> getPersonByKey(string login, string password, string list_type)
It means that getPersonByKey
returns either a User*
or a Stuff*
. You can construct a variant from any of their options, so you can just return one pointer of those types.
The method getPerson()
is not declared in your example so I cannot fully rewrite your example. However, if getPerson()
returns an User*
, you can directly return its value and it will be converted to a boost::variant<User*, Stuff*>
containing the returned value.
Note that boost::variant<User*, Stuff*>
must be either User*
or Stuff*
. It cannot be empty. So, if you return a default boost::variant<User*, Stuff*>
, you are actually returning a default pointer to User
.
As boost::variant is used to hold one of the template parameters, it makes no sense to declare it like:
boost::variant<T, T>
Because it means that you can store either a T or and T. In this case, you can just use a T type.
It is very easy to check which type is store in the variant. The easiest way is to use the get
method:
User **user = boost::get<User*>(&variant);
The variable user
will get a pointer to the stored value if a pointer to User
was stored or nullptr
if a Stuff
pointer was stored. There are more ways to access the value, like using visitors.
You can find more information in the variant tutorial.
Upvotes: 1