std::variant cout in C++ - c++

I am relatively new to CPP and have recently stumbled upon std::variant for C++17.
However, I am unable to use the << operator on such type of data.
Considering
#include <iostream>
#include <variant>
#include <string>
using namespace std;
int main() {
variant<int, string> a = "Hello";
cout<<a;
}
I am unable to print the output. Is there any short way of doing this? Thank you so much in advance.

You can use std::visit if you don't want to use std::get.
#include <iostream>
#include <variant>
struct make_string_functor {
std::string operator()(const std::string &x) const { return x; }
std::string operator()(int x) const { return std::to_string(x); }
};
int main() {
const std::variant<int, std::string> v = "hello";
// option 1
std::cout << std::visit(make_string_functor(), v) << "\n";
// option 2
std::visit([](const auto &x) { std::cout << x; }, v);
std::cout << "\n";
}

use std::get
#include <iostream>
#include <variant>
#include <string>
using namespace std;
int main() {
variant<int, string> a = "Hello";
cout << std::get<string>(a);
}
If you want to get automatically, it can't be done without knowing its type. Maybe you can try this.
string s = "Hello";
variant<int, string> a = s;
cout << std::get<decltype(s)>(a);

#include <iostream>
#include <variant>
#include <string>
int main( )
{
std::variant<int, std::string> variant = "Hello";
std::string string_1 = std::get<std::string>( variant ); // get value by type
std::string string_2 = std::get<1>( variant ); // get value by index
std::cout << string_1 << std::endl;
std::cout << string_2 << std::endl;
//may throw exception if index is specified wrong or type
//Throws std::bad_variant_access on errors
//there is also one way to take value std::visit
}
Here is the description link: https://en.cppreference.com/w/cpp/utility/variant

Related

Request for member 'end' in 'arrPtr' etc

I am trying to pass an array of strings off to a function so that it will sort it along with a Class Template array object of strings which I don't even know what that would look like. But as it is right now. When I use size() inside of main it works just fine but when I use size() inside a function I am typing up it throws out this error.
#include <iostream>
#include <iomanip>
#include <array>
#include <string>
#include <algorithm> // contains sort and binary_search
using namespace std;
void sortArrays(string arr[]);
int main()
{
array<string, 5> hello = {"Hello", "world", "How", "Are", "You"};
sortArrays(&hello[0]);
}
void sortArrays(string array[])
{
string *arrPtr = array;
sort(*arrPtr.begin(), *arrPtr.end());
cout << endl << endl;
}
Like this, std::array it's easy to pass by reference.
#include <algorithm>
#include <array>
#include <iostream>
#include <vector>
#include <string>
void sortArray(std::array<std::string,5>& arr)
{
std::sort(arr.begin(),arr.end());
}
int main()
{
std::array<std::string, 5> hello = { "Hello", "world", "How", "Are", "You" };
sortArray(hello);
for (const auto& str : hello)
{
std::cout << str << " ";
}
std::cout << std::endl;
}

Struggling to create a Boost-Bimap containing std::bitset

I have a number of strings and their bitset equivalents. I need to be able to look up equivalents in both directions, i.e. "str to bitset" and "bitset to str". I believe boost-bimap would be the right container for this job.
I managed to get this to work with strings and integers but my string / bitset bimap does not compile. I am using VS2019 with the latest boost release.
Integer example works:
#include <boost/bimap.hpp>
#include <string>
#include <iostream>
int main()
{
typedef boost::bimap<std::string, int> bimap_str_int_t;
bimap_str_int_t bimap1;
bimap1.insert(bimap_str_int_t::value_type("A", 1));
std::cout << bimap1.left.at("A") << '\n'; //prints 1
std::cout << bimap1.right.at(1) << '\n'; // prints A
}
Bitset example fails to compile:
#include <boost/bimap.hpp>
#include <string>
#include <iostream>
#include <bitset>
int main()
{
typedef std::bitset<3> bitset_t;
typedef boost::bimap<std::string, bitset_t> bimap_str_bitset_t;
bimap_str_bitset_t bimap2;
bitset_t bits{ "010" };
bimap2.insert(bimap_str_bitset_t::value_type("A", bits));
std::cout << bimap2.left.at("A") << '\n';
std::cout << bimap2.right.at(bits) << '\n';
}
The bitset example creates the following compiler error:
boost_test.cpp(20): message : see reference to class template instantiation 'boost::bimaps::bimap' being compiled
I am not sure how to fix this and would greatly appreciate any hints.
The issue is that std::bitset has no operator< - one of the requirements of any STL-like ordered collection.
To fix this, you need to supply a comparison function - here's one way you might try:
#include <boost/bimap.hpp>
#include <string>
#include <iostream>
#include <bitset>
typedef std::bitset<3> bitset_t;
struct compare_bitset {
bool operator()(const bitset_t& x, const bitset_t& y) const {
return x.to_ulong() < y.to_ulong();
}
};
int main()
{
using bitset_set = boost::bimaps::set_of<bitset_t, compare_bitset>;
typedef boost::bimap < std::string, bitset_set> bimap_str_bitset_t;
bimap_str_bitset_t bimap2;
bitset_t bits{ "010" };
bimap2.insert(bimap_str_bitset_t::value_type("A", bits));
std::cout << bimap2.left.at("A") << '\n';
std::cout << bimap2.right.at(bits) << '\n';
}

Using rolling accumulators in unordered maps in a Class

I'm trying to use an unordered map to hold rolling accumulators in a class.
First let me show what works. Here is an accumulator within a class that works as expected without the map. Note that the accumulator needs to be initialized in the initialization list.
#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
namespace nmbstacc = boost::accumulators;
typedef nmbstacc::accumulator_set<double, nmbstacc::stats<nmbstacc::tag::rolling_mean >> MACC;
class RollMean {
public:
MACC m_acc;
RollMean(void) : m_acc(nmbstacc::tag::rolling_window::window_size = 3) {}
};
int main()
{
RollMean obj;
obj.m_acc(0.5);
obj.m_acc(1.5);
obj.m_acc(2.5);
obj.m_acc(3.5);
std::cout << "roll_mean: " << nmbstacc::rolling_mean(obj.m_acc) << std::endl;
std::getchar();
return 0;
}
However, what I need is an unordered map to hold these accumulators in a class but can't seems to figure out how to get the following program to compile. I'm not sure how to declare the mainmap container without first initializing the rolling accumulator.
#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
#include <unordered_map>
namespace nmbstacc = boost::accumulators;
typedef nmbstacc::accumulator_set<double, nmbstacc::stats<nmbstacc::tag::rolling_mean >> MACC;
class RollMean {
public:
MACC m_acc;
std::unordered_map<std::string, MACC> mainmap;
RollMean(std::string name) : m_acc(nmbstacc::tag::rolling_window::window_size = 3) {
mainmap.emplace(name, m_acc);
}
};
int main()
{
RollMean obj("a");
obj.mainmap["a"](1.0);
std::cout << "roll_mean: " << nmbstacc::rolling_mean(obj.mainmap["a"]) << std::endl;
std::getchar();
return 0;
}
I get the following error:
Error C2679 binary '[': no operator found which takes a right-hand operand of type 'boost::parameter::keyword' (or there is no acceptable conversion)
Thanks.
Like #jv_ hinted, map[key] is a mutating operation, which inserts a default constructed element if none exists.
However, there's no default constructor for your element type. Therefore, you can't use that operator.
If you use obj.mainmap.at("a") instead of obj.mainmap["a"], you'll get an exception on missing keys instead.
Live On Coliru
#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
#include <unordered_map>
namespace nmbstacc = boost::accumulators;
typedef nmbstacc::accumulator_set<double, nmbstacc::stats<nmbstacc::tag::rolling_mean> > MACC;
class RollMean {
public:
MACC m_acc;
std::unordered_map<std::string, MACC> mainmap;
RollMean(std::string name) : m_acc(nmbstacc::tag::rolling_window::window_size = 3) { mainmap.emplace(name, m_acc); }
};
int main() {
RollMean obj("a");
obj.mainmap.at("a")(1.0);
std::cout << "roll_mean: " << nmbstacc::rolling_mean(obj.mainmap.at("a")) << std::endl;
}
Prints:
roll_mean: 1

Using range for on a boost FUSION sequence

I am trying to print struct members as follows:
#include <iostream>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
struct Node {
int a = 4;
double b = 2.2;
};
BOOST_FUSION_ADAPT_STRUCT(Node, a, b)
int main() {
Node n;
for (auto el: n) { // What do I put instead of n here?
std::cout << el << std::endl;
}
return 0;
}
This is wrong of course, since n is just a struct. How do I put for a sequence that the range for can work with instead of n?
You cannot use range-based for for this case. It's metaprogramming, each member iterator has its own type. You can traverse using fusion::for_each, or with hand-writen struct.
#include <iostream>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/for_each.hpp>
struct Node {
int a = 4;
int b = 2.2;
};
BOOST_FUSION_ADAPT_STRUCT(Node, a, b)
struct printer
{
template<typename T>
void operator () (const T& arg) const
{
std::cout << arg << std::endl;
}
};
int main() {
Node n;
boost::fusion::for_each(n, printer());
return 0;
}

BOOST_PP_REPEAT with boost::fusion::size

I want to iterate in compile time over struct and write to output number of iteration. Just to mention - in real case I will pass some more parameters in data.
#include <iostream>
#include <string>
#include <vector>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/size.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
struct MyStruct
{
int x;
int y;
};
BOOST_FUSION_ADAPT_STRUCT(
MyStruct,
(int, x)
(int, y)
)
#define PRINT(unused, number, data) \
std::cout << number << std::endl;
int main()
{
MyStruct s;
std::cout << boost::fusion::size(s) << std::endl;
//line below works - it iterate and write output
BOOST_PP_REPEAT(2, PRINT, "here I will pass my data")
//this won't compile
//BOOST_PP_REPEAT(boost::fusion::size(s), PRINT, "here i will pass my data")
}
How to fix problematic line so it will work when I will add more members in structure? I need solution for C++03 :(
Instead of using BOOST_PP_REPEAT, you can use the boost::fusion::for_each which goes through every element. example:
#include <iostream>
#include <string>
#include <vector>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/size.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
struct MyStruct {
int x;
int y;
};
BOOST_FUSION_ADAPT_STRUCT(
MyStruct,
(int, x)
(int, y)
)
template<typename Data>
struct PrintWithData {
PrintWithData(Data data) : data(data) {}
template<typename T>
operator()(const T& thingToBePrinted)
{
std::cout << thingToBePrinted << std::endl;
}
Data data;
};
int main()
{
MyStruct s;
//this will compile
boost::fusion::for_each(s, PrintWithData<std::string>("here I will pass my data"));
}
Here is exact solution for this problem (asked more general question later, and found answear which solve this problem too): https://stackoverflow.com/a/31713778/4555790