It's been a while that I've been doing C++ but I'm not familiar with templates.
Recently, I tried to write a class that wrap a std::vector<std::tuple<Types...>>. This class must have member functions, and I really need to be able to iterate over the tuple. In fact, if I am able to print every element of a tuple (in the order), I would be able to do everything I need.
I found a solution using a cast, but I'm not really confident with it since it is based on a cast that I don't really like (plus, when I try to use static_cast, it doesn't compile anymore).
My question is, is the following code correct, portable, is it a hack and should I find another way to do this than to use this cast ? Also, this cast is probably a runtime-cast right ? Is there a way to do what I want without this ?
std::ostream& operator<<(std::ostream& out, std::tuple<> const& tuple)
{
return out; // Nothing to do here
}
template<typename First, typename... Types>
std::ostream& operator<<(std::ostream& out, std::tuple<First, Types...> const& tuple)
{
out << std::get<0>(tuple) << " ";
// The cast that I don't like
return out << (std::tuple<Types...>&) tuple;
}
int main()
{
auto tuple = std::make_tuple(1, 2.3, "Hello");
std::cout << tuple << std::endl;
return 0;
}
Thank you in advance for your answers.
Use std::index_sequence_for for fun and profit.
template <typename TupleLike, size_t ... Inds>
std::ostream& PrintHelper(std::ostream& out, TupleLike const& tuple, std::index_sequence<Inds...>)
{
int unused[] = {0, (void(out << std::get<Inds>(tuple) << " "), 0)...};
(void)unused;
return out;
}
template<typename... Types>
std::ostream& operator<<(std::ostream& out, std::tuple<Types...> const& tuple)
{
return PrintHelper(out, tuple, std::index_sequence_for<Types...>());
}
EDIT : Live Demo. Thanks to #dyp. This uses an expansion trick from this answer.
I found another way to do what I want. I used this article that can print the elements of a tuple in the descending order, and I use a second index J == std::tuple_size<std::tuple<Types...>>::value - I so I can specialize the template when I==0.
template<std::size_t I, std::size_t J, typename... Types>
struct printHelper
{
std::ostream& operator()(std::ostream& out, std::tuple<Types...> const& tuple)
{
out << std::get<J>(tuple) << " ";
// Recursive call without cast
return printHelper<I-1,J+1,Types...>{}(out, tuple);
};
};
// Specialization on the last element when I==0
template<std::size_t J, typename... Types>
struct printHelper<0,J,Types...>
{
std::ostream& operator()(std::ostream& out, std::tuple<Types...> const& tuple)
{
// Nothing to do here
return out;
}
};
template<typename... Types>
std::ostream& operator<<(std::ostream& out, std::tuple<Types...> const& tuple)
{
return printHelper<std::tuple_size<std::tuple<Types...>>::value, 0, Types...>{}(out, tuple);
}
Related
I have the following code that works, but I am confused about how it works.
template<typename ...Args>
void print(Args&&... args) {
(std::cout << ... << std::forward<Args>(args)) << '\n';
}
int main()
{
print(1,2.0,"3");
}
output:
123
My confusion:
I would expect 321 printed.
I would like to have this order:
cout << forward(args) << ...
but I can not get that to compile...
The position of ... specifies left or right associativity, but doesn't change the order of arguments - it lets you choose between (std::cout << x) << y and std::cout << (x << y). The later likely would not compile.
If you want to print values in the reversed order you need to use some trick. Here is the example:
#include <type_traits>
#include <iostream>
template <typename T>
struct ReversePrinter
{
ReversePrinter(T val) : val(val) { }
template <typename U>
ReversePrinter<T> operator<<(const ReversePrinter<U>& other) const
{
std::cout << other.val;
return *this;
}
T val;
};
template <typename T>
std::ostream& operator<<(std::ostream& stream, const ReversePrinter<T>& val)
{
return stream << val.val;
}
template <typename... Args>
void print(Args... args)
{
std::cout << (ReversePrinter(args) << ...);
}
int main()
{
print(100, 200, 300.0); //prints 300200100
}
Fold expressions respect the precedence and associativity of the operator you use. But for certain operators you can do more creative left and right folds. The only variable to account for is the sequencing of the operands. C++17 introduced a happens before relation between the right and left side of assignment operators, so they act more intuitively. The right side, and all associated side effects must happen first.
So a completely self contained solution to your question can look like this:
template <typename... Args>
void print(Args&& ...args) {
int dum = 0;
(... = (std::cout << args, dum));
}
Here it is, live.
It's using a comma to print, while assigning dum to itself in a way that forces the evaluation order we want.
With few trickeries, (can't come anything better at the moment) you could do following:
Not sure if there's any straight forward way
// Your original function
template<typename ...Args>
void print(Args&&... args) {
(std::cout << ... << std::forward<Args>(args)) << '\n';
}
template<typename ...Args>
struct changeorder;
template<>
struct changeorder<>
{
template<typename ...OtherArgs>
static void invoke(OtherArgs const&... otherargs)
{
print(otherargs...);
}
};
template<typename T, typename ...Args>
struct changeorder<T, Args...>
{
template<typename ...OtherArgs>
static void invoke(T const& t, Args const&... args,
OtherArgs const&... otherargs)
{
// 1st parameter send first
changeorder<Args...>::invoke(args..., t, otherargs...);
}
};
template<typename A, typename ...Args>
void reverseprint(A const& a, Args const&... args)
{
changeorder<Args...>::invoke(args..., a);
}
Demo Here
The standard go-to solution for template-magic is std::index_sequence.
And for making arguments indexable one uses std::tuple.
template <std::size_t... N, class T>
void print_reverse_impl(std::index_sequence<N...>, std::ostream& os, T t) {
(os << ... << std::get<std::tuple_size_v<T> - N - 1>(t));
}
template <class... T>
void print_reverse(std::ostream& os, T&&... t) {
print_reverse_impl(std::make_index_sequence<sizeof...(t)>(), os, std::forward_as_tuple(t...));
}
Still, if you have static_for() in your tool-box (you really should), this is simpler:
template <class... T>
void print_reverse(std::ostream& os, T&&... t) {
static_for<sizeof...(t)>([&](auto n){
os << std::get<sizeof...(t) - n - 1>(std::forward_as_tuple(t...));
});
}
With C++20, one could also write it as:
void print_reverse(std::ostream& os, auto&&... t) {
[&]<auto... N>(std::index_sequence<N...>, auto all){
(os << ... std::get<sizeof...(t) - N - 1>(all));
}(std::make_index_sequence<sizeof...(t)>(), std::forward_as_tuple(t...));
}
As an aside, I cut out all the calls to std::forward, because those rvalue-references would just be reduced down to lvalue-references by the standard-library anyway.
I write a variadic template to print all the arguments with recursion:
#include <iostream>
using std::ostream; using std::istream;
using std::cin; using std::cout; using std::endl;
template <typename T, typename... Args>
ostream &myprint(ostream &os, const T &t, const Args&... rest) {
if (sizeof...(rest)) {
os << t << ", ";
return myprint(os, rest...);
}
else
return os << t;
}
int main(int argc, char *argv[]) {
myprint(cout, "hello");
return 0;
}
But when I compiles it with g++ -std=c++1y, it complains:
error: no matching function for call to ‘myprint(std::ostream&)’
return myprint(os, rest...);
In the function myprint, I have checked the value of sizeof...(rest). And when it is 0, it will not call myprint(os, rest...). So I don't know why it will call myprint(std::ostream&).
And I have also searched for the related question, I have found that it needs a base case. But why do I need a base case, and can't sizeof... work in a variadic template?
And for the simple indefinite recursive case:
template <typename T, typename... Args>
ostream &myprint(ostream &os, const T &t, const Args&... rest) {
os << t << ", "; // print the first argument
return print(os, rest...); // recursive call; print the other arguments
}
The code above can't be compiled at all for the same error.
For the if statement you used, both the statement-true and statement-false must be valid, whether the condition yields to the result of true or false.
You can use constexpr if since C++17; when the value of condition is false, the statement-true will be discarded. e.g.
if constexpr (sizeof...(rest)) {
os << t << ", ";
return myprint(os, rest...);
}
else
return os << t;
If you can't use C++17, you can add another template overload for the case that the number of arguments is only one, to stop the recursion, e.g.
template <typename T>
ostream &myprint(ostream &os, const T &t) {
return os << t;
}
template <typename T, typename... Args>
ostream &myprint(ostream &os, const T &t, const Args&... rest) {
os << t << ", ";
return myprint(os, rest...);
}
LIVE
songyuanyao's answer explains why it's invalid and provides a solution for C++17. Alternatively, you could have a base case to myprint prior to that.
template <typename T>
ostream &myprint(ostream &os, const T &t) {
return os << t;
}
template <typename T, typename... Args>
ostream &myprint(ostream &os, const T &t, const Args&... rest) {
os << t << ", ";
return myprint(os, rest...);
}
I've seen types that have corresponding to_string() function, but haven't overloaded operator<<(). So, when inserting to stream, one has to << to_string(x) which is verbose. I'm wondering whether it's possible to write a generic function that users operator<<() if supported and falls back to << to_string() if not.
SFINAE is overkill, use ADL.
The trick is to make sure that an operator<< is available, not necessarily the one supplied by the type definition:
namespace helper {
template<typename T> std::ostream& operator<<(std::ostream& os, T const& t)
{
return os << to_string(t);
}
}
using helper::operator<<;
std::cout << myFoo;
This trick is commonly used in generic code which needs to choose between std::swap<T> and a specialized Foo::swap(Foo::Bar&, Foo::Bar&).
Try
template <typename T>
void print_out(T t) {
print_out_impl(std::cout, t, 0);
}
template <typename OS, typename T>
void print_out_impl(OS& o, T t,
typename std::decay<decltype(
std::declval<OS&>() << std::declval<T>()
)>::type*) {
o << t;
}
template <typename OS, typename T>
void print_out_impl(OS& o, T t, ...) {
o << t.to_string();
}
LIVE
Yes, it is possible.
#include <iostream>
#include <sstream>
#include <string>
#include <type_traits>
struct streamy
{
};
std::ostream&
operator<<(std::ostream& os, const streamy& obj)
{
return os << "streamy [" << static_cast<const void *>(&obj) << "]";
}
struct stringy
{
};
std::string
to_string(const stringy& obj)
{
auto oss = std::ostringstream {};
oss << "stringy [" << static_cast<const void *>(&obj) << "]";
return oss.str();
}
template <typename T>
std::enable_if_t
<
std::is_same
<
std::string,
decltype(to_string(std::declval<const T&>()))
>::value,
std::ostream
>&
operator<<(std::ostream& os, const T& obj)
{
return os << to_string(obj);
}
int
main()
{
std::cout << streamy {} << '\n';
std::cout << stringy {} << '\n';
}
The generic operator<< will only be available if the expression to_string(obj) is well-typed for obj a const T& and has a result of type std::string. As you have already conjectured in your comment, this is indeed SFINAE at work. If the decltype expression is not well-formed, we will get a substitution failure and the overload will disappear.
However, this will likely get you into troubles with ambiguous overloads. At the very least, put your fallback operator<< into its own namespace and only drag it in locally via a using declaration when needed. I think you will be better off writing a named function that does the same thing.
namespace detail
{
enum class out_methods { directly, to_string, member_str, not_at_all };
template <out_methods> struct tag {};
template <typename T>
void
out(std::ostream& os, const T& arg, const tag<out_methods::directly>)
{
os << arg;
}
template <typename T>
void
out(std::ostream& os, const T& arg, const tag<out_methods::to_string>)
{
os << to_string(arg);
}
template <typename T>
void
out(std::ostream& os, const T& arg, const tag<out_methods::member_str>)
{
os << arg.str();
}
template <typename T>
void
out(std::ostream&, const T&, const tag<out_methods::not_at_all>)
{
// This function will never be called but we provide it anyway such that
// we get better error messages.
throw std::logic_error {};
}
template <typename T, typename = void>
struct can_directly : std::false_type {};
template <typename T>
struct can_directly
<
T,
decltype((void) (std::declval<std::ostream&>() << std::declval<const T&>()))
> : std::true_type {};
template <typename T, typename = void>
struct can_to_string : std::false_type {};
template <typename T>
struct can_to_string
<
T,
decltype((void) (std::declval<std::ostream&>() << to_string(std::declval<const T&>())))
> : std::true_type {};
template <typename T, typename = void>
struct can_member_str : std::false_type {};
template <typename T>
struct can_member_str
<
T,
decltype((void) (std::declval<std::ostream&>() << std::declval<const T&>().str()))
> : std::true_type {};
template <typename T>
constexpr out_methods
decide_how() noexcept
{
if (can_directly<T>::value)
return out_methods::directly;
else if (can_to_string<T>::value)
return out_methods::to_string;
else if (can_member_str<T>::value)
return out_methods::member_str;
else
return out_methods::not_at_all;
}
template <typename T>
void
out(std::ostream& os, const T& arg)
{
constexpr auto how = decide_how<T>();
static_assert(how != out_methods::not_at_all, "cannot format type");
out(os, arg, tag<how> {});
}
}
template <typename... Ts>
void
out(std::ostream& os, const Ts&... args)
{
const int dummy[] = {0, ((void) detail::out(os, args), 0)...};
(void) dummy;
}
Then use it like so.
int
main()
{
std::ostringstream nl {"\n"}; // has `str` member
out(std::cout, streamy {}, nl, stringy {}, '\n');
}
The function decide_how gives you full flexibility in deciding how to output a given type, even if there are multiple options available. It is also easy to extend. For example, some types have a str member function instead of an ADL find-able to_string free function. (Actually, I already did that.)
The function detail::out uses tag dispatching to select the appropriate output method.
The can_HOW predicates are implemented using the void_t trick which I find very elegant.
The variadic out function uses the “for each argument” trick, which I find even more elegant.
Note that the code is C++14 and will require an up-to-date compiler.
Based on the answer of #MSalters (credits goes to him), this one solves my problem and should make a complete answer.
#include <iostream>
#include <string>
#include <type_traits>
struct foo_t {};
std::string to_string(foo_t) {
return "foo_t";
}
template <class CharT, class Traits, class T>
typename std::enable_if<std::is_same<CharT, char>::value,
std::basic_ostream<CharT, Traits>&>::type
operator<<(std::basic_ostream<CharT, Traits>& os, const T& x) {
return os << to_string(x);
}
int main() {
std::cout << std::string{"123"} << std::endl;
std::cout << foo_t{} << std::endl;
}
I'm playing with variadic templates and I'm currently trying to implement operator<< for tuple.
I've tried the following code but it doesn't compile (GCC 4.9 with -std=c++11).
template<int I, typename ... Tlist>
void print(ostream& s, tuple<Tlist...>& t)
{
s << get<I>(t) << ", ";
if(I < sizeof...(Tlist)){
print<I+1>(s,t);
}
}
template<typename ... Tlist>
ostream& operator<<(ostream& s, tuple<Tlist...> t)
{
print<0>(s,t);
return s;
}
The error message is very cryptic and long, but it basically says that there is no matching function call for get. Can someone explain to me why?
Thanks.
EDIT:
Here is the template instantiation I'm using
auto t = make_tuple(5,6,true,"aaa");
cout << t << endl;
Code in an if (blah) { block } is compiled and must be valid even if the condition blah is false.
template<bool b>
using bool_t = std::integral_constant<bool, b>;
template<int I, typename ... Tlist>
void print(std::ostream& s, std::tuple<Tlist...> const& t, std::false_type) {
// no more printing
}
template<int I, typename ... Tlist>
void print(std::ostream& s, std::tuple<Tlist...> const& t, std::true_type) {
s << std::get<I>(t) << ", ";
print<I+1>(s, t, bool_t<((I+1) < sizeof...(Tlist))>{});
}
template<typename ... Tlist>
std::ostream& operator<<(std::ostream& s, std::tuple<Tlist...> const& t)
{
print<0>(s,t, bool_t<(0 < sizeof...(Tlist))>{});
return s;
}
should work. Here we use tag dispatching to control which overload we recursively call: the 3rd argument is true_type if I is a valid index for the tuple, and false_type if not. We do this instead of an if statement. We always recurse, but when we reach the end of the tuple, we recurse into the terminating overload.
live example
As an aside, it is ambiguous if overloading << for two types defined in std is compliant with the standard: it depends if std::tuple<int> is a "user defined type" or not, a clause that the standard does not define.
On top of that, it is considered best practice to overload operators for a type within the namespace of that type, so it can be found via ADL. But, overloading << inside std is illegal under the standard (you cannot inject new overloads into std). The result can be somewhat surprising behavior in some cases, where the wrong overload is found, or an overload is not found.
You have to use specialization or SFINAE as the branch even if it is not taken generates the instantiation:
template<int I, typename ... Tlist>
void print(ostream& s, tuple<Tlist...>& t)
{
s << get<I>(t) << ", ";
if(I < sizeof...(Tlist)){
print<I+1>(s,t); // Generated even if I >= sizeof...(Tlist)
}
}
And so you would have infinite instantiation of print if get<sizeof...(Tlist)> doesn't produce an error sooner.
You may wrote it without recursion with:
template<std::size_t ... Is, typename Tuple>
void print_helper(std::ostream& s, const Tuple& t, std::index_sequence<Is...>)
{
int dummy[] = { 0, ((s << std::get<Is>(t) << ", "), 0)...};
(void) dummy; // remove warning for unused var
}
template<typename Tuple>
void print(std::ostream& s, const Tuple& t)
{
print_helper(s, t, std::make_index_sequence<std::tuple_size<Tuple>::value>());
}
Live example
I have a set of templates/functions that allow me to print a tuple/pair assuming that each type in the tuple/pair has operator<< defined for it. Unfortunately, due to 17.4.3.1, it is illegal to add my operator<< overloads to std. Is there another way to get ADL to find my operator<<? If not, is there any actual harm in wrapping my overload in namespace std{}?
The code for anyone interested: (I'm using gcc-4.5)
namespace tuples {
using ::std::tuple;
using ::std::make_tuple;
using ::std::get;
namespace detail {
template< typename...args >
size_t size( tuple<args...> const& )
{
return sizeof...(args);
};
template<size_t N>
struct for_each_ri_impl
{
template<typename Func, typename Tuple>
void operator()(Func func, Tuple const& arg)
{
for_each_ri_impl<N-1>()(func, arg );
func( get<N>( arg ), size(arg) - N - 1 );
}
};
template<>
struct for_each_ri_impl<0>
{
template<typename Func, typename Tuple>
void operator()(Func func, Tuple const& arg)
{
func( get<0>( arg ), size(arg) - 1 );
}
};
}//detail
template<typename Func, typename ... Args>
void for_each_ri( tuple<Args...>const& tup, Func func )
{
detail::for_each_ri_impl< sizeof...(Args)-1>()( func, tup );
}
struct printer {
std::ostream& out;
const std::string& str;
explicit printer( std::ostream& out=std::cout, std::string const& str="," ) : out(out), str(str) { }
template<typename T>void operator()(T const&t, size_t i=-1) const { out<<t; if(i) out<<str; }
};
//Should this next line go into namespace std? Is there another way?
template<typename ... Args>
std::ostream& operator<<(std::ostream& out, std::tuple< Args... > const& tup)
{
out << '[';
tuples::for_each_ri( tup, tuples::printer(out,", ") );
return out << ']';
}
} //tuples
//Edits --
int main()
{
using namespace std;
cout<<make_tuple(1,'a',"Hello")<<endl;
return 0;
}
Compiling the above yields:
test.cpp: In function 'int main()':
test.cpp:69:31: error: cannot bind 'std::ostream' lvalue to 'std::basic_ostream&&' > /opt/local/include/gcc45/c++/ostream:579:5: error: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char, _Traits = std::char_traits, _Tp = std::tuple]'
Put your own light wrapper class around it and then overload operator<< to use that. However beware that even if your light wrapper has an implicit constructor you will probably still need to use it explicitly when you pass it to operator<<
template< typename ...VA_ARGS >
struct format_tuple
{
typedef tuple<VA_ARGS...> tuple_type;
// any format variables
const tuple_type & tup;
format_tuple( const tuple_type& t): tup(t) {}
};
template< typename ...VA_ARGS > format_tuple<VA_ARGS...> makeFormatTuple( const tuple<VA_ARGS...> & t )
{
return format_tuple( t );
}
template<typename ...VA_ARGS>
std::ostream& operator<<( std::ostream& os, const format_tuple<VA_ARGS...> & ft )
{
// original implementation
}
This is an outline as I'm not sure exactly how to do it with variadic templates although it should be possible. You can easily implement several versions though with 1, 2, 3, etc.parameters, eg:
template<typename T1, typename T2, typename T3>
class format_tuple_3; //etc
template<typename T1, typename T2, typename T3>
format_tuple_3<T1, T2, T3> makeFormatTuple( tuple<T1,T2,T3> const&); //etc
The harm is someone else (such as in a third party library you want to use) also adding these declarations to std. Even if theirs behave identically, you'll violate the ODR.
Just put these in your project's namespace:
namespace kitsune_ymg {
// Op<< overloads here.
// Your "normal" stuff.
void normal_stuff() {
std::cout << std::pair<int, int>(42, 3);
}
And then anything in your project can use them.
I'm still not sure exactly why this doesn't work for you, but it seems you want something like:
namespace kitsune_ymg {
namespace tuples {
// Op<< overloads here.
}
using namespace tuples;
// Your "normal" stuff.
}
namespace completely_separate_project {
using kitsune_ymg::tuples;
// Now you can use those op<< overloads in this scope, too.
void perfectly_normal_beast() {
std::cout << std::pair<int, int>(42, 3);
}
}
You mustn't add your own operator<< to std. However, you can write an adapter for tuples, or one for streams, and use that, with a minimal amount of change to the call sites.
I'll assume C++17 or newer (to use structured bindings and fold expressions), although the question is obviously much older.
Adapt the tuple
#include <ostream>
#include <tuple>
template<typename... Args>
struct printable_tuple
{
typedef std::tuple<Args...> tuple_type;
const tuple_type& t;
// implicit converting constructor
printable_tuple(const tuple_type& t)
: t(t)
{}
};
template<typename... Args>
std::ostream& operator<<(std::ostream& os, const printable_tuple<Args...>& tuple)
{
const char *sep = "";
os << '[';
std::apply([&os,&sep](auto&&...args){((os << sep << args, sep = ","),...);}, tuple.t);
return os << ']';
}
#include <iostream>
int main()
{
std::cout << format_tuple{std::tuple{1,'a',"Hello"}} << '\n';
}
This is the least intrusive, as we can use the returned stream normally (if (os << tuple), for instance), but it requires wrapping each and every argument.
Adapt the stream
#include <tuple>
template<typename Stream>
class tuple_ostream
{
Stream& os;
public:
// conversions from and to Stream
tuple_ostream(Stream& os) : os{os} {}
operator Stream&() const { return os; };
// generic forwarding <<
template<typename T>
tuple_ostream& operator<<(const T&t)
{
os << t;
return *this;
}
// overload for tuples
template<typename... Args>
tuple_ostream& operator<<(const std::tuple<Args...>&t)
{
const char *sep = "";
os << '[';
std::apply([this,&sep](auto&&...args){((os << sep << args, sep = ","),...);}, t);
os << ']';
return *this;
}
};
#include <iostream>
int main()
{
tuple_ostream{std::cout} << std::tuple{1,'a',"Hello"} << '\n';
}
Adapting the stream is obviously simpler when we need to write several tuples to the same stream, but we can no longer directly use the returned stream as the original unless we add more functions to the wrapper.
Hat-tip to CashCow's answer for a starting point for this one.