是否有合法的方法来使用operator <<打印元组和对?
我有一套模板/函数,允许我打印一个元组/对,假定元组/对中的每个类型都有operator<<
为其定义。 不幸的是,由于17.4.3.1,将我的operator<<
overloads添加到std
是非法的。 是否有另一种方法让ADL找到我的operator<<
? 如果没有,在namespace std{}
中包装我的重载是否有任何实际的危害?
任何感兴趣的代码:(我使用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;
}
编译上面的结果:
test.cpp:在函数'int main()'中:
test.cpp:69:31:错误:无法将'std :: ostream'左值绑定到'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 ::元组]”
把你自己的轻包装类放在它周围,然后重载运算符<<来使用它。 但是要注意,即使你的轻包装器有一个隐含的构造函数,当你将它传递给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
}
这是一个大纲,因为我不确定如何使用可变参数模板来做到这一点,尽管它应该是可能的。 尽管使用1,2,3等参数,您可以轻松实现多个版本,例如:
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
伤害是别人(比如在你想使用的第三方库中)也将这些声明添加到std中。 即使他们的行为一致,你也会违反ODR。
只需将它们放在项目的名称空间中:
namespace kitsune_ymg {
// Op<< overloads here.
// Your "normal" stuff.
void normal_stuff() {
std::cout << std::pair<int, int>(42, 3);
}
然后你的项目中的任何东西都可以使用它们。
我仍然不确定为什么这不适合你,但似乎你想要的东西是这样的:
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);
}
}
链接地址: http://www.djcxy.com/p/50921.html
上一篇: Is there a legal way to print tuples and pairs using operator<<?