Forward boost::variant from a visitor to another - c++

I want to call a visitor on a boost variant from inside another visitor. Consider the following code:
struct visitor1 : boost::static_visitor<>
{
void operator()(const int& i) const { std::cout << "visitor1:" << i; }
void operator()(const std::string & str) const { std::cout << "visitor1, string: " << str}
};
struct visitor2 : boost::static_visitor<>
{
void operator()(const int& i) const
{
// apply visitor1 here
boost::apply_visitor(visitor1(), /* is there a context reference to the variant here? */)
std::cout << "visitor 2 applied visitor 1";
}
void operator()(const std::string & str) const { //... }
};
int main()
{
boost::variant< int, std::string> v = 5;
boost::apply_visitor(visitor2 (), v );
}
Should output:
visitor1: 5
Visitor 2 applied visitor 1

If you want to take the variant, just call it directly (witout apply_visitor).
If you want to take it in addition just use bind or similar:
Live On Coliru
#include <boost/variant.hpp>
#include <boost/bind.hpp>
#include <iostream>
struct visitor1 : boost::static_visitor<>
{
void operator()(const int& i) const { std::cout << "visitor1:" << i << "\n"; }
void operator()(const std::string & str) const { std::cout << "visitor1, string: " << str << "\n"; }
};
struct visitor2 : boost::static_visitor<>
{
template <typename Variant>
void operator()(const int& i, Variant const& v) const
{
boost::apply_visitor(visitor1(), v);
std::cout << "visitor 2 applied visitor 1" << " (int " << i << ")\n";
}
template <typename Variant>
void operator()(const std::string & str, Variant const& v) const {
boost::apply_visitor(visitor1(), v);
std::cout << "visitor 2 applied visitor 1" << " (string " << str << ")\n";
}
};
int main()
{
using V = boost::variant< int, std::string>;
for (V v : { V{5}, V{"something"} })
boost::apply_visitor(boost::bind(visitor2(), _1, boost::ref(v)), v);
}
Prints
visitor1:5
visitor 2 applied visitor 1 (int 5)
visitor1, string: something
visitor 2 applied visitor 1 (string something)
Alternative Without Bind
If you prefer DIY you can emulate the "bind" easily:
Live On Coliru
template <typename V>
struct visitor2 {
typedef void result_type;
V const* _ref;
void operator()(const int& i) const {
boost::apply_visitor(visitor1(), *_ref);
std::cout << "visitor 2 applied visitor 1" << " (int " << i << ")\n";
}
void operator()(const std::string & str) const {
boost::apply_visitor(visitor1(), *_ref);
std::cout << "visitor 2 applied visitor 1" << " (string " << str << ")\n";
}
};
int main()
{
using V = boost::variant< int, std::string>;
for (V v : { V{5}, V{"something"} })
boost::apply_visitor(visitor2<V>{&v}, v);
}
Printing
visitor1:5
visitor 2 applied visitor 1 (int 5)
visitor1, string: something
visitor 2 applied visitor 1 (string something)
A Stylistic Note:
I like to make the function object Variant-aware, and then you can hide the "double bind":
Live On Coliru
struct visitor2 {
typedef void result_type;
template <typename... Ts>
void operator()(boost::variant<Ts...> const& v) const {
return boost::apply_visitor(boost::bind(*this, _1, boost::cref(v)), v);
}
template <typename Variant>
void operator()(const int& i, Variant const& v) const {
boost::apply_visitor(visitor1(), v);
std::cout << "visitor 2 applied visitor 1" << " (int " << i << ")\n";
}
template <typename Variant>
void operator()(const std::string & str, Variant const& v) const {
boost::apply_visitor(visitor1(), v);
std::cout << "visitor 2 applied visitor 1" << " (string " << str << ")\n";
}
};
int main()
{
using V = boost::variant< int, std::string>;
for (V v : { V{5}, V{"something"} })
visitor2{}(v);
}
Prints
visitor1:5
visitor 2 applied visitor 1 (int 5)
visitor1, string: something
visitor 2 applied visitor 1 (string something)

Related

Output of map of set custom objects c++

So I have a map that has user defined keys and the values in it are sets of objects too. So I'm trying to write some print function but I have no idea how to do that. (I'm kind of new to maps and sets).
My problem function:
void print() const
{
for (auto& itr : my_mmap)
{
std::cout << "Key for this set:" << itr.first << "\n\n";
for (int i = 0; i< itr.second.size(); i++)
{
std::cout << itr.second[i] << std::endl;
}
}
}
Here's my class:
#include <iostream>
#include <map>
#include <string>
#include <tuple>
#include <utility>
#include <set>
class Enclosing {
private:
class Key {
int m_number;
std::string m_name;
public:
Key(int num, std::string name) :m_number(num), m_name(std::move(name)) {};
bool operator<(const Key& rhs) const {
return std::tie(m_number, m_name) < std::tie(rhs.m_number, rhs.m_name);
}
friend std::ostream& operator<<(std::ostream& os, const Key& k) {
return os << '{' << k.m_number << ',' << k.m_name << '}';
}
};
class Nested {
std::string m_str;
double m_dbl;
bool m_boolean;
public:
Nested(std::string str, double dbl, bool boolean) :m_str(std::move(str)), m_dbl(dbl), m_boolean(boolean) {};
friend std::ostream& operator<<(std::ostream& os, const Nested& n) {
return os << '{' << n.m_str << ',' << n.m_dbl << ',' << n.m_boolean << '}';
}
};
std::multimap<Key, std::set<Nested>> my_mmap;
public:
template <class... Args>
void add_new_object_to_mmap(Args&&... args) {
my_mmap.emplace(std::piecewise_construct, std::forward<Args>(args)...);
}
/*
THAT PROBLEM FUNCTION
*/
void print() const
{
for (auto& itr : my_mmap)
{
std::cout << "Key for this set:" << itr.first << "\n\n";
for (int i = 0; i< itr.second.size(); i++)
{
std::cout << itr.second[i] << std::endl;
}
}
}
static Enclosing& get_singleton() {
static Enclosing instance;
return instance;
}
};
}
So the problem is that I am getting an error "no operator "[]" match these operands". How can I output my map and set in the best way?
The problem is that we cannot use indexing on a std::set. Thus itr.second[i] is not valid because itr.second is an std::set.
To solve this you can use a range-based for loop as shown below:
for (const auto&elem:itr.second)
{
std::cout << elem << std::endl;
}

How to deduce template by struct's member

Suppose I have some structs and each of them holds one enum as a member.
I want to call a method of a struct but depending on a struct's member, like in the code example:
#include <iostream>
#include <string>
#include <type_traits>
enum class Type{
lowercase = 0,
uppercase
};
struct Low{
static constexpr Type cp = Type::lowercase;
};
struct Up{
static constexpr Type cp = Type::uppercase;
};
template<typename Case, typename=void>
struct Printer
{
void print_g(const std::string& s){
std::cout << "just s: " << s << std::endl;
}
};
template<typename X>
struct Printer<X, std::enable_if_t<X::cp == Type::lowercase, void>>
{
void print_g(const std::string& s){
std::cout << "lowercase " << std::nouppercase << s << std::endl;
}
};
template<typename X>
struct Printer <X, std::enable_if_t<X::cp == Type::uppercase, void>>
{
void print_g(const std::string& s){
std::cout << "uppercase " << std::uppercase << s << std::endl;
}
};
int main()
{
Printer<Low> pl;
pl.print_g("hello1");
Printer<Up> p2;
p2.print_g("hello2");
}
But this solution doesn't look quite elegant to me.
Especially the part typname=void in the first template.
Only then code compiles. Why is that the case?
And is there any better (more elegant) solution for this template specialization?
In C++17, you can use if constexpr:
template <typename X>
struct Printer
{
void print_g(const std::string& s)
{
if constexpr(X::cp == Type::lowercase)
{
std::cout << "lowercase " << std::nouppercase << s << std::endl;
}
else if constexpr(X::cp == Type::uppercase)
{
std::cout << "uppercase " << std::uppercase << s << std::endl;
}
else
{
std::cout << "just s: " << s << std::endl;
}
}
};
If you do not have access to C++17, consider these options:
Use a regular if...else statement. There's no code that needs to be conditionally compiled in your example.
Implement static_if in C++14. Here's a talk I gave that explains how to do it: Implementing static control flow in C++14
You can fully specialize Printer for Low and Up.
template<class Case>
struct Printer
{
void print_g(const std::string& s) {
std::cout << "just s: " << s << std::endl;
}
};
template<>
struct Printer<Low>
{
void print_g(const std::string& s) {
std::cout << "lowercase " << std::nouppercase << s << std::endl;
}
};
template<>
struct Printer<Up>
{
void print_g(const std::string& s) {
std::cout << "uppercase " << std::uppercase << s << std::endl;
}
};
Notice that the enum does not come into play at all. If you need to specialize for the enum, you can do that too.
template<Type Case>
struct PrinterHelper
{
void print_g(const std::string& s) {
std::cout << "just s: " << s << std::endl;
}
};
template<>
struct PrinterHelper<Type::lowercase>
{
void print_g(const std::string& s) {
std::cout << "lowercase " << std::nouppercase << s << std::endl;
}
};
template<>
struct PrinterHelper<Type::uppercase>
{
void print_g(const std::string& s) {
std::cout << "uppercase " << std::uppercase << s << std::endl;
}
};
template<class Case>
using Printer = PrinterHelper<Case::cp>;
I would likely just go with:
enum struct Casing
{
Lower,
Upper
};
template<Casing>
struct printer;
template<>
struct printer<Casing::Lower>
{
...
};
template<>
struct printer<Casing::Upper>
{
...
};

Template class to call some function of other classes based on their presence and priority and more type restrictions like const and case sensitivity

I have structs/classes like these:
struct LD { //Login detail
std::string username;
std::string password;
std::string toString() const {
return "Username: " + username
+ " Password: " + password;
}
};
struct UP { //User Profile
std::string name;
std::string email;
ostream& pPrint(ostream& ost) const {
ost << "Name: " << name
<< " Email: " << email;
return ost;
}
std::string toString() const {
return "NULLSTRING";
}
};
struct CD { //ContactDetails
std::string m_phoneNumber;
std::string m_address;
ostream& pPrint(ostream& ost) { //NO CONST must not print
ost << "PhoneNumber: " << m_phoneNumber << " Address:" << m_address;
return ost;
}
} ;
struct H {
std::string hobbies;
ostream& PPrint(ostream& ost) { //its not case equivalent and not const so it should not be called
ost << "Hobbies: " << m_hobbies;
return ost;
}
} ;
struct PD {
std::string cardNumber;
ostream& pPrint(ostream& ost) const {
ost << "CardNumber: " << m_cardNumber;
return ost;
}
} ;
struct BN {
std::string m_bankName;
std::string toString() const {
return "BANKNAME";
}
ostream& simplePrint(ostream& ost) const {
ost << "BankName: " << m_bankName;
return ost;
}
} ;
struct DI {
std::string toString() const {
return "i0S";
}
ostream& pPrint(ostream& ost) const {
ost << "Android: JellyBean";
return ost;
}
};
I am creating a template PPrint class which will call pPrint function of that class if its present. If not, it will call toString function of that class if its also not available it will print NO print function.
Priorities:
Invoke pPrint
Invoke toString
Simply output NO print Function
My main function:
int main() {
LD ld = { "And", "Ap" };
UP up = { "James Brannd", "jamens#goo.com" };
CD cd = { "+9198799911", "355 B. Bway, NY" };
H hb = { "sing, dance, read"};
PD pd = { "444411113336667732222" };
BN bn = { "SBI" };
DI di;
std::cout << PPrint <UP> (up) << std::endl;
std::cout << PPrint <LD> (ld) << std::endl;
std::cout << PPrint <CD> (cd) << std::endl;
std::cout << PPrint <H>(hb) << std::endl;
std::cout << PPrint <PD> (pd) << std::endl;
std::cout << PPrint <BN> (bn) << std::endl;
std::cout << PPrint <DI> (di) << std::endl;
}
Now I have created this class as below:
template<class...>
using void_t = void;
// pPrint
template<typename T, typename = void_t<>>
struct HaspPrintMethod : std::false_type{};
template<typename T>
struct HaspPrintMethod<T, void_t<decltype(std::declval<T> ().pPrint(std::declval<std::ostream&>()))>> : std::true_type{};
// PPrint
template<typename T, typename = void_t<>>
struct HasPPrintMethod : std::false_type{};
template<typename T>
struct HasPPrintMethod<T, void_t<decltype(std::declval<T>().PPrint(std::declval<std::ostream&>()))>> : std::true_type{};
template<typename T>
using HasPPrintMethod_t = typename HasPPrintMethod<T>::type;
// both pPrint and PPrint
template<typename T>
struct HasAnyPPrintMethod : std::integral_constant<bool, HasPPrintMethod<T>::value || HaspPrintMethod<T>::value>{};
template<typename T>
using HasAnyPPrintMethod_t = typename HasAnyPPrintMethod<T>::type;
template<typename T, typename=void_t<>>
struct HastoStringMethod : std::false_type{};
template<typename T>
struct HastoStringMethod<T, void_t<decltype(std::declval<T>().toString())>> : std::true_type{};
template<typename T>
using HastoStringMethod_t = typename HastoStringMethod<T>::type;
template <class T>
class PPrint {
public:
PrettyPrint(T m)
{
CallPrint(m, HasAnyPPrintMethod_t<T>());
}
std::string buf;
private:
void CallPrint( T& m, std::true_type)
{
CallPPrint(m, HasPPrintMethod_t<T>());
}
void CallPPrint(T& m, std::true_type)
{
std::ostringstream os;
m.PPrint(os); //need correction as pPrint is only priority for THis "NO print function" if pPrint is nor there and toString is not there I mean it should ignored
buf = os.str();
}
void CallPrettyPrint(T& m, std::false_type)
{
std::ostringstream os;
m.pPrint(os); //only i want this one as 1st priority PPrint must be not used anywhere , should not be printed
buf = os.str();
}
void CallPrint( T& m, std::false_type)
{
CallPrintNoPPrint(m, HastoStringMethod_t<T>());
}
void CallPrintNoPPrint( T& m, std::true_type)
{
buf = m.toString();
}
void CallPrintNoPrettyPrint( T& m, std::false_type)
{
buf = "NO print Function";
}
};
It's not correct because it's not distinguishing for const and its giving error like below for my compiler but running on others and printing H's function (which it must not print):
error: ‘struct UP’ has no member named ‘PPrint’
m.PrettyPrint(os);
But it's running fine on ideone and Coliru.
How should I create such class or remove such errors?
Main challenges are:
Prioriy (mentioned earlier)
Case sensitive same function
Const type distinguish function should be pPrint only and const too.
You cant what's inside any of the struct and main function that is template class should be seperate and independent.
Only C++11 standards
The class should work for this two prototype only:
ostream& pPrint(ostream& ost) const // case sentive for pPrint
std::string toString() const
References:
Template class to call some named function of other classes based on their presence and priority
Check if a class has a member function of a given signature
You can use something like this to reduce the boilerplate of your solution and solve the issue:
struct SimplyOutput {};
struct ToString: SimplyOutput {};
struct PPrint: ToString {};
template<typename T>
void pPrintImpl(SimplyOutput, const T &) {
// Do whatever you want here
}
template<typename T>
auto pPrintImpl(ToString, const T &t)
-> decltype(t.toString()) {
// Do whatever you want here
}
template<typename T>
auto pPrintImpl(PPrint, const T &t)
-> decltype(t.pPrint(std::declval<std::ostream>())) {
// Do whatever you want here
}
template<typename T>
auto pPrint(const T &t)
-> decltype(pPrintImpl(PPrint{}, t)) {
return pPrintImpl(PPrint{}, t);
}
Overloading, inheritance and sfinae will do the job.
Below a minimal, working example based on the code in the question:
#include<iostream>
#include<string>
#include<sstream>
struct LD { //Login detail
std::string username;
std::string password;
std::string toString() const {
return "Username: " + username
+ " Password: " + password;
}
};
struct UP { //User Profile
std::string name;
std::string email;
std::ostream& pPrint(std::ostream& ost) const {
ost << "Name: " << name
<< " Email: " << email;
return ost;
}
std::string toString() const {
return "NULLSTRING";
}
};
struct CD { //ContactDetails
std::string m_phoneNumber;
std::string m_address;
std::ostream& pPrint(std::ostream& ost) { //NO CONST must not print
ost << "PhoneNumber: " << m_phoneNumber << " Address:" << m_address;
return ost;
}
} ;
struct H {
std::string m_hobbies;
std::ostream& PPrint(std::ostream& ost) { //its not case equivalent and not const so it should not be called
ost << "Hobbies: " << m_hobbies;
return ost;
}
} ;
struct PD {
std::string m_cardNumber;
std::ostream& pPrint(std::ostream& ost) const {
ost << "CardNumber: " << m_cardNumber;
return ost;
}
} ;
struct BN {
std::string m_bankName;
std::string toString() const {
return "BANKNAME";
}
std::ostream& simplePrint(std::ostream& ost) const {
ost << "BankName: " << m_bankName;
return ost;
}
} ;
struct DI {
std::string toString() const {
return "i0S";
}
std::ostream& pPrint(std::ostream& ost) const {
ost << "Android: JellyBean";
return ost;
}
};
template<typename T>
class PPrint {
struct SimplyOutputTag {};
struct ToStringTag: SimplyOutputTag {};
struct PPrintTag: ToStringTag {};
template<typename U = T>
void internal(SimplyOutputTag, const U &) {
buf = "NO print Function";
}
template<typename U = T>
auto internal(ToStringTag, const U &u)
-> decltype(u.toString(), void()) {
buf = u.toString();
}
template<typename U = T>
auto internal(PPrintTag, const U &u)
-> decltype(u.pPrint(std::declval<std::ostringstream &>()), void()) {
std::ostringstream os;
u.pPrint(os);
buf = os.str();
}
public:
PPrint(const T &t) {
internal(PPrintTag{}, t);
}
std::string get() const { return buf; }
private:
std::string buf;
};
template<typename T>
std::ostream & operator << (std::ostream &os, const PPrint<T> &pp) {
os << pp.get();
return os;
}
int main() {
LD ld = { "And", "Ap" };
UP up = { "James Brannd", "jamens#goo.com" };
CD cd = { "+9198799911", "355 B. Bway, NY" };
H hb = { "sing, dance, read"};
PD pd = { "444411113336667732222" };
BN bn = { "SBI" };
DI di;
std::cout << PPrint <UP> (up) << std::endl;
std::cout << PPrint <LD> (ld) << std::endl;
std::cout << PPrint <CD> (cd) << std::endl;
std::cout << PPrint <H>(hb) << std::endl;
std::cout << PPrint <PD> (pd) << std::endl;
std::cout << PPrint <BN> (bn) << std::endl;
std::cout << PPrint <DI> (di) << std::endl;
}

Output a tuple within an STL list

void output_list_contents(std::list<tuple<string, int, double,int>> &my_list)
{
for(std::list<tuple<string, int, double,int> >::iterator it =my_list.begin(); it!= my_list.end(); ++it)
{
}
}
I'm trying to output the information from all tuples stored within an STL list. I don't know the syntax and I have spent the past hour googling for an answer, but sadly I haven't come across anything. I'm struggling with the syntax and logic to get access to the tuples stored within.
Can anyone help me out here please?
Something like:
void output_list_contents(std::list<tuple<string, int, double,int>> &my_list)
{
for(const auto& e : my_list)
{
std::cout << std::get<0>(e) << " " << std::get<1>(e) << " "
<< std::get<2>(e) << " " << std::get<3>(e) << std::endl;
}
}
First overload operator<< for tuple<string, int, double,int>:
std::ostream& opertaor<<(std::ostream& out,
tuple<string,int,double,int> const & t)
{
return out << "{" << std::get<0>(t)
<< "," << std::get<1>(t)
<< "," << std::get<2>(t)
<< "," << std::get<3>(t) << "}";
}
then use it in the loop as:
for(std::list<tuple<string, int, double,int> >::iterator it =my_list.begin();
it!= my_list.end(); ++it)
{
std::cout << *it << std::endl;
}
Oh that is ugly. Better use range-based for loop and auto:
for(auto const & item : my_list)
std::cout << item << std::endl;
Hope that helps.
A generalized implementation of operator<< for std::tuple would be this:
namespace detail
{
template<int ... N>
struct seq
{
using type = seq<N...>;
template<int I>
struct push_back : seq<N..., I> {};
};
template<int N>
struct genseq : genseq<N-1>::type::template push_back<N-1> {};
template<>
struct genseq<0> : seq<> {};
template<typename ... Types, int ...N>
void print(std::ostream & out, std::tuple<Types...> const & t, seq<N...>)
{
const auto max = sizeof...(N);
auto sink = {
(out << "{", 0),
(out << (N?",":"") << std::get<N>(t) , 0)...,
(out << "}", 0)
};
}
}
template<typename ... Types>
std::ostream& operator<<(std::ostream & out, std::tuple<Types...> const & t)
{
detail::print(out, t, typename detail::genseq<sizeof...(Types)>::type());
return out;
}
This generalized operator<< should be able to print std::tuple with any number of template arguments, as long as all template arguments support operator<< in turn.
Test code:
int main()
{
std::cout << std::make_tuple(10, 20.0, std::string("Nawaz")) << std::endl;
std::cout << std::make_tuple(10, 20.0, std::string("Nawaz"), 9089) << std::endl;
}
Output:
{10,20,Nawaz}
{10,20,Nawaz,9089}
Online Demo :-)
void output_list_contents(std::list<std::tuple<std::string, int, double, int>>& my_list)
{
for (auto tup : my_list)
{
print_tuple(tup);
}
}
And this is how print_tuple looks:
template <typename... Ts, int... Is>
void print_tuple(std::tuple<Ts...>& tup, std::index_sequence<Is...>)
{
auto l = { ((std::cout << std::get<Is>(tup)), 0)... };
}
template <typename... Ts>
void print_tuple(std::tuple<Ts...>& tup)
{
print_tuple(tup, std::index_sequence_for<Ts...>{});
}

How to iterate through an unknown type?

I've got this function:
set<int> Search(const _Type & hayHeap) const {
set<int>myset;
for (vector<typename>::const_iterator i = needle.begin(); i != needle.end(); ++i) {
cout << (*i) << " ";
}
return myset;
};
and needle is defined like this:vector<string> needle;
Now I need to create another iterator, that will iterate through hayHeap. But the problem is, that I don't know, what type will it be. It could be a single string or vector of <int>/<string> as well. So when there is a string, it iterates only once, if there is some vector it iterates (myVector.count()-1)-times. How to make this type independent iterator?
In C++03:
template <typename C>
set<int> Search(const C& hayHeap) const {
set<int>myset;
for (typename C::const_iterator i = needle.begin(); i != needle.end(); ++i) {
cout << (*i) << " ";
}
return myset;
};
In C++11:
template <typename C>
set<int> Search(const C& hayHeap) const {
set<int>myset;
for (auto& i : needle) {
cout << i << " ";
}
return myset;
};
Depending on your actual needs, you'd replace int by typename C::value_type
OK I think I understood your question now. I think you are looking for some kind of type function. Something of this sort.
template<typename T>
struct my_selector {
static void search(T& t) {
cout << " Single string / int search" << endl;
bool b = t == "needle";
cout << b;
}
};
template<typename T>
struct my_selector<vector<T>> {
static void search(vector<T>& needle) {
cout << " Vector search" << endl;
for (typename vector<T>::const_iterator i = needle.begin();
i != needle.end(); ++i)
{
cout << (*i) << " ";
}
}
};
int main() {
typedef std::vector<std::string> _Type;
_Type needle(4,"s");
// Search function is selected based on type of _Type.
my_selector<_Type>::search(needle);
// typedef string _Type;
// _Type needle = "needle";
// // Search function is selected based on type of _Type.
// my_selector<_Type>::search(needle);
}