是否有合法的方法打印元组和对使用operator<<? [英] Is there a legal way to print tuples and pairs using operator<<?
问题描述
运算符<
。不幸的是,由于17.4.3.1,将运算符<<
重载添加到 std
还有另一种方法让ADL找到我的运算符<<
?如果没有,在 namespace std {}
? 中封装我的重载是否有任何实际的伤害感兴趣的(我使用gcc-4.5)
命名空间元组{
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(get< N(arg),size(arg)-N-1);
}
};
模板<>
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&出口;
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<< if(i)out<< str; }
};
//这下一行应该进入命名空间std吗?还有别的办法吗?
template< typename ... Args>
std :: ostream&运算符<<<(std :: ostream& out,std :: tuple< Args ...> const& tup)
{
out< '[';
tuples :: for_each_ri(tup,tuples :: printer(out,,));
return out<< ']';
}
} // tuples
//编辑 -
int main()
{
使用命名空间std ;
cout<< make_tuple(1,'a',Hello)<<
return 0;
}
编译上述产量:
test.cpp:在函数'int main()':
test.cpp:69:31:error:can not bind'std :: ostream'lvalue 'std :: basic_ostream&&'> / opt / local / include / gcc45 / c ++ / ostream:579:5:error:初始化'std :: basic_ostream< _CharT,_Traits& std :: operator<<<<<<(std :: basic_ostream< _CharT,_Traits&&&& const _Tp&)[with _CharT = char,_Traits = std :: char_traits,_Tp = std :: tuple]'
在你自己的轻包装类周围,然后重载operator<使用。但是请注意,即使你的轻包装有一个隐式构造函数,你可能仍需要明确使用它,当你传递给operator<<
模板< typename ... VA_ARGS>
struct format_tuple
{
typedef tuple< VA_ARGS ...> tuple_type;
//任何格式变量
const tuple_type& ;
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)
{
//原实现
}
这是一个大纲,因为我不知道如何做可变模板,虽然应该是可能的。你可以很容易地实现几个版本,虽然有1,2,3等参数,例如:
template< typename T1,typename T2,类型名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
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
这篇关于是否有合法的方法打印元组和对使用operator<<?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!