-
Notifications
You must be signed in to change notification settings - Fork 0
Variant (boost::variant)
Define a boost::variant
with a number of different types. The only requirement is that one of them must be user defined. The task is to write the contents of the boost::variant
variable to std::cout
regardlessly of which type is the current one in use. Implementation wise boost::variant
is streamable, if and only if all types it has been parameterized with are streamables.
To start with our user defined type is not streamable. In other words, writing something like std::cout << v << std::endl;
will not work, assuming that v is a boost::variant
. Therefore inspect the boost::variant
API and determine which methods to use in order to handle the above.
#include <boost/variant.hpp>
#include <string>
#include <iostream>
int main()
{
boost::variant<int, std::string, double> v;
v = 255;
std::cout << boost::get<int>(v) << std::endl;
v = "Hello, World!";
std::cout << boost::get<std::string>(v) << std::endl;
v = 3.1415;
std::cout << boost::get<double>(v) << std::endl;
return 0;
}
The output is:
255
Hello, World!
3.1415
To complete this exercise make your type streamable by implementing std::ostream& operator <<(std::ostream&, const <your type>&)
. Now test the code std::cout << v << std::endl;
that did not work before
To implement the overload, we first need to make a template, since we don't want to make an overload for every variant type.
#include <boost/variant.hpp>
#include <iostream>
#include <string>
template <typename T>
std::ostream &operator<<(std::ostream &os, const boost::variant<T> &var)
{
os << boost::get<T>(var);
return os;
}
int main()
{
boost::variant<int, std::string, double> v;
v = 255;
std::cout << v << std::endl;
v = "Hello, World!";
std::cout << v << std::endl;
v = 3.1415;
std::cout << v << std::endl;
return 0;
}
Output:
255
Hello, World!
3.1415
As seen in the previous exercise we need to determine which type a given boost::variant actually contains before performing some desired deed, which obviously is not surprising. However it means that I/we as developers would have to write the same test code every time. Fortunately boost::variant supports visitation that alleviates us from performing this task. Stuff to do:
- Explain visitation
- Write a functor that has an function operator overloaded for each type in your
boost::variant
. Remember to inherit properly fromboost::static_visitor
. - In each of these overloads write out the variable’s contents as well as some text such that it is clear from where it came
- Try to compile your code before all overloads have been completed - What happens and why?
#include <boost/type_index.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <string>
#include <vector>
class FunctorClass : public boost::static_visitor<>
{
private:
/* data */
public:
template <typename T> void operator()(T t) const
{
std::cout << boost::typeindex::type_id<T>().pretty_name() << ' ' << t
<< std::endl;
}
};
int main()
{
FunctorClass visitor;
std::vector<boost::variant<int, std::string, double, char>> vec;
vec.push_back("Hello, World!");
vec.push_back(420.69);
vec.push_back(42);
vec.push_back('F');
std::for_each(vec.begin(), vec.end(), boost::apply_visitor(visitor));
}
Output:
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Hello, World!
double 420.69
int 42
char F
Made by: Frederik Both Rokkjær, Frederik Kronvang Gade and Christian Olsen