9

operator<<タプル/ペアの各タイプが定義されていると仮定して、タプル/ペアを出力できるテンプレート/関数のセットがあります。残念ながら、17.4.3.1 により、operator<<オーバーロードをに追加することは違法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: エラー: 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) の引数 1 を初期化しています [with _CharT = char 、_Traits = std::char_traits、_Tp = std::tuple]'


おそらく最良のアイデアは、サイトのブログ レイアウトを再作成することです。時間がかかり、基本的な html + css のスキルが必要になりますが、これが最良の選択肢です。

4

3 に答える 3

2

独自のライト ラッパー クラスを配置し、それを使用するために operator<< をオーバーロードします。ただし、ライト ラッパーに暗黙的なコンストラクターがある場合でも、それを 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
于 2011-02-22T09:58:05.877 に答える
2

害は、他の誰か (使用したいサードパーティのライブラリなど) もこれらの宣言を 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);
}
}
于 2011-02-22T09:42:48.067 に答える