是否有合法的方法打印元组和对使用operator<<? [英] Is there a legal way to print tuples and pairs using operator<<?

查看:175
本文介绍了是否有合法的方法打印元组和对使用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&lt;&lt;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆