3

私は次のことができるようにしたいと思います:

std::cerr << std::chrono::system_clock::now() << std::endl;

そして、以下を取得します。

Wed May  1 11:11:12 2013

だから私は次のように書いた:

template<typename Clock, typename Duration>
std::ostream &operator<<(std::ostream &stream,
  const std::chrono::time_point<Clock, Duration> &time_point) {
  const time_t time = Clock::to_time_t(time_point);
#if __GNUC__ > 4 || \
    ((__GNUC__ == 4) && __GNUC_MINOR__ > 8 && __GNUC_REVISION__ > 1)
  // Maybe the put_time will be implemented later?
  struct tm tm;
  localtime_r(&time, &tm);
  return stream << std::put_time(tm, "%c");
#else
  char buffer[26];
  ctime_r(&time, buffer);
  buffer[24] = '\0';  // Removes the newline that is added
  return stream << buffer;
#endif
}

これは機能しますが、これを別の名前空間から呼び出すと問題が発生し続けます。これはグローバル名前空間にあるべきであるというのは正しいですか?

4

2 に答える 2

4

正しい関数が確実に呼び出されるようにしたい場合は、usingそれを呼び出すコードのスコープに宣言を配置する必要があります。

例えば:

namespace pretty_time {
  /* your operator<< lives here */
}


void do_stuff() {
  using namespace pretty_time;   // One way to go is this line
  using pretty_time::operator<<; // alternative that is more specific (just use one of these two lines, but not both)
  std::cout << std::chrono::system_clock::now();
}
于 2013-05-22T13:06:41.013 に答える
3

ごちゃごちゃしたものを自分の に保持し、namespaceどちらも所有していない 2 つの型に対して演算子をオーバーロードするというやや失礼なことを避ける 1 つの方法は、出力構文をもう少し冗長にすることです。

std::cerr << pretty_print::format(std::system_clock::now()) << std::endl;

次のように:

namespace pretty_print {
  template<typename T>
  struct print_wrapper { // boost::noopy optional -- if so, use it with && as an argument
    T const& data;
    print_wrapper( T const& t ): data(t) {}
  };
  template<typename T>
  print_wrapper<T> format( T const& t ) {
    return {t};
  }
  template<typename Clock, typename Duration>
  std::ostream &operator<<(std::ostream &stream,
    print_wrapper<std::chrono::time_point<Clock, Duration>>&& time_point)
  {
    // ...
  }
}

time_point.dataオーバーロード内の生データを取得するためのアクセス<<

演算子は、ラップされた型を使用するときに、使用する場所にプルしなくても、<<ADL (引数依存ルックアップ) を介して検出されます! これを使用するには、使用するか、現在のスコープにプルすることができます。print_wrapper<>namespacepretty_print::format(blah)using pretty_print::formatformat

実際にはT、独自のオーバーロードのカスタム セットで使用するために型にフラグを立てました。私はこの「薄いタイプのラッパー」のテクニックが好きですstd::move

doubleこれにより、「 s のフォーマット方法が嫌いだ」と言うことができ、<<をより適切にフォーマットするprint_wrapper<double>.

副次的な利点として、特殊化/オーバーロードprint_wrapperし、formatフォーマット引数を取ることができpretty_print::format( std::system_clock::now(), pretty_print::eDate::YMD )ますpretty_print::eFmt::compact

于 2013-05-22T18:45:37.993 に答える