У меня есть набор шаблонов / функций, которые позволяют мне печатать кортеж / пару, предполагая, что для каждого типа в кортеже / паре определен operator <<
. К сожалению, из-за 17.4.3.1 запрещено добавлять мои operator <<
перегрузки в std
. Есть ли другой способ заставить ADL найти мой оператор <<
? Если нет, есть ли реальный вред в том, что моя перегрузка помещается в пространство имен 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 ():
перегружается наstd
. Есть ли другой способ заставить ADL найти мойоператор <<
? Если нет, есть ли реальный вред в том, что моя перегрузка помещается в пространство имен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 ():
перегружается наstd
. Есть ли другой способ заставить ADL найти мойоператор <<
? Если нет, есть ли реальный вред в том, что моя перегрузка помещается в пространство имен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: ошибка: невозможно привязать lvalue 'std :: ostream' к 'std :: basic_ostream &&'> / opt / local / include / gcc45 / c ++ / ostream: 579: 5: ошибка: инициализация аргумента 1 из 'std :: basic_ostream <_CharT, _Traits> & std :: operator << (std :: basic_ostream <_CharT, _Traits> &&, const _Tp &) [с _CharT = char, _Traits = std :: char_traits, _Tp = std :: tuple] '