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...>{});
}
Related
I have a small bit of code.
I want to know if i could cut out my ProcessArg function
I would like to loop the parameter pack from inside my call function.
Im i best to use a lambda function in initializer_list or something else, if so how do i do it.
Thanks
template <class R, class Arg>
R ProcessArg(Arg&& arg) {
std::cout << typeid(arg).name() << (std::is_reference<Arg>::value ? "&" : "") << std::endl;
//std::cout << std::boolalpha << std::is_reference<Arg>::value << std::endl; // not always true
return R();
}
template <typename R, typename... Args>
R CallFunction(Args&&... args) {
std::size_t size = sizeof...(Args);
std::initializer_list<R>{ProcessArg<R>(std::forward<Args>(args)) ...};
return R();
}
template<typename Fn> class FunctionBase;
template<typename R, typename... Args>
class FunctionBase <R(*)(Args...)> {
public:
FunctionBase() {}
R operator()(Args&&... args) { // Args&& is a universal reference
return CallFunction<R>(std::forward<Args>(args)...);
}
};
int foo(int a, int& b) {
std::cout << std::boolalpha << std::is_reference<decltype(a)>::value << std::endl; // falae
std::cout << std::boolalpha << std::is_reference<decltype(b)>::value << std::endl; // true
return a + b;
}
int main() {
int in = 10;
foo(1, in);
FunctionBase<decltype(&foo)> func;
func(1, in);
}
With c++17 fold-expressions, you can replace:
std::initializer_list<R>{ProcessArg<R>(std::forward<Args>(args)) ...};
with:
((std::cout << typeid(args).name()
<< (std::is_reference<Args>::value ? "&" : "")
<< std::endl
), ...);
Or with a lambda expression to improve readability:
auto process = [](auto&& arg) {
std::cout << typeid(arg).name()
<< (std::is_lvalue_reference<decltype(arg)>::value ? "&" : "")
<< std::endl;
};
(process(std::forward<Args>(args)), ...);
In c++20:
auto process = [] <typename Arg> (Arg&& arg) {
std::cout << typeid(arg).name()
<< (std::is_reference<Arg>::value ? "&" : "")
<< std::endl;
};
(process(std::forward<Args>(args)), ...);
This short C++17 program:
#include <iostream>
template <typename T> void output(T x)
{
if constexpr (std::is_integral<decltype(x)>::value) {
std::cout << static_cast<int>(x) << " is integral" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}
int main()
{
char x = 65;
output(x);
bool t = true;
output(t);
return 0;
}
Has this output:
65 is integral
1 is integral
In the template function named output, how can one detect that the argument x is boolean and not a number?
The plan is to output the value with std::cout << std::boolalpha <<, but only if the type is bool.
std::is_integral checks if a type is one of the following types: bool, char, char16_t, char32_t, wchar_t, short, int, long, long long (source). If you want to check if a type is the same as another type, std::is_same can be used. Both can be combined to get the wanted result:
template <typename T> void output(T x)
{
if constexpr (std::is_integral<decltype(x)>::value && !std::is_same<decltype(x), bool>::value) {
std::cout << static_cast<int>(x) << " is integral but not a boolean" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}
or, since we already know the type of decltype(x), which is T:
template <typename T> void output(T x)
{
if constexpr (std::is_integral<T>::value && !std::is_same<T, bool>::value) {
std::cout << static_cast<int>(x) << " is integral but not a boolean" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}
Another way can be to use a template specialization. This makes sure the other overload is being used to handle the boolean value.
template <typename T> void output(T x)
{
if constexpr (std::is_integral<T>::value) {
std::cout << static_cast<int>(x) << " is integral but not a boolean" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}
template <> void output(bool x)
{
std::cout << x << " is a boolean" << std::endl;
}
namespace fmt {
namespace adl {
template<class T>
void output( std::ostream& os, T const& t ) {
os << t;
}
void output( std::ostream& os, bool const& b ) {
auto old = os.flags();
os << std::boolalpha << b;
if (!( old & std::ios_base::boolalpha) )
os << std::noboolalpha; // restore state
}
template<class T>
void output_helper( std::ostream& os, T const& t ) {
output(os, t); // ADL
}
}
template<class T>
std::ostream& output( std::ostream& os, T const& t ) {
adl::output_helper( os, t );
return os;
}
}
now fmt::output( std::cout, true ) prints true, while fmt::output( std::cout, 7 ) prints 7.
You can extend fmt::output by creating a function in either fmt::adl or in the type T's namespace called output that takes a std::ostream& and a T const&.
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>
{
...
};
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)
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);
}