PAPAmidNIGHT
PAPAmidNIGHT

Reputation: 59

boost variant return type

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

Answers (1)

J. Calleja
J. Calleja

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

Related Questions