C++ 標準ライブラリにテンプレートがありcomplex<>
、オーバーロードされた << 演算子があり、(real_part, im_part) 形式で複素数を出力します。出力形式がまったく異なるものに変更されるように、複素数に対するその演算子の動作を変更する必要があります。具体的には、出力をフォームにする必要がありますreal_part\tim_part
。それ、どうやったら出来るの?
5 に答える
を直接置き換える方法はありoperator <<
ませんが、いくつかのオプションがあります。まず、複素数を出力する独自の関数を書くことができます:
template <typename T> void PrintComplex(const complex<T>& c) {
/* ... */
}
引き続きナイス ストリーム構文を使用する場合は、a をラップするラッパー クラスを作成し、それを別の方法で出力するcomplex
独自のクラスを定義するという方法があります。operator <<
例えば:
template <typename T> class ComplexPrinter {
public:
/* Conversion constructor allows for implicit conversions from
* complex<T> to ComplexPrinter<T>.
*/
ComplexPrinter(const complex<T>& value) : c(value) {
// Handled in initializer list
}
/* Output the complex in your own format. */
friend ostream& operator<< (ostream& out, const ComplexPrinter& cp) {
/* ... print in your own format ... */
}
private:
complex<T> c;
};
これができたら、次のように書くことができます
cout << ComplexPrinter<double>(myComplex) << endl;
オブジェクトをラップする次のような関数を作成することで、これをさらにきれいにすることができます。
template <typename T>
ComplexPrinter<T> wrap(const complex<T>& c) {
return ComplexPrinter<T>(c);
}
これにより、次のように記述できます
cout << wrap(myComplex) << endl;
これは完璧ではありませんが、かなり良いです。
complex<T>
上記のラッパーについて注意すべきことの 1 つは、 s をsに変換できるように暗黙的な変換コンストラクターが設定されていることですComplexPrinter<T>
。これは、 がある場合vector< complex<T> >
、カスタム コードを使用して を呼び出して印刷できることを意味します。
vector< complex<double> > v = /* ... */
copy (v.begin(), v.end(), ostream_iterator< ComplexPrinter<double> >(cout, " "));
出力では、暗黙的な変換コンストラクターがcomplex<double>
s をラッパーに変換し、カスタム コードが印刷を行います。
非常に冒険的になり、風に注意を払いたい場合は、次にcomplex
示すように、元の への参照のみを格納するようにクラスを作成することもできます。
template <typename T> class ComplexPrinter {
public:
/* Conversion constructor allows for implicit conversions from
* complex<T> to ComplexPrinter<T>.
*/
ComplexPrinter(const complex<T>& value) : c(value) {
// Handled in initializer list
}
/* Output the complex in your own format. */
friend ostream& operator<< (ostream& out, const ComplexPrinter& cp) {
/* ... print in your own format ... */
}
private:
const complex<T>& c;
};
これにより、コピーが完全に排除され、ラッパーが実際の の周りの薄いベニヤになりますcomplex
。(しゃれは意図されていません)。元のオブジェクトがスコープ外になるスコープ境界を越えてこれらのオブジェクトを渡さないようにする場合は、非常に注意する必要がありますが、それが必要な場合は、うまくいく可能性があります。
お役に立てれば!
template<class T>
struct my_complex_format_type {
std::complex<T> const &x;
my_complex_format_type(std::complex<T> const &x) : x (x) {}
friend std::ostream& operator<<(std::ostream &out,
my_complex_format_type const &value)
{
out << "format value.x however you like";
return out;
}
};
template<class T>
my_complex_format_type<T> my_complex_format(std::complex<T> const &x) {
return x;
}
void example() {
std::cout << my_complex_format(some_complex);
}
の特定のインスタンス化についてはcomplex<T>
、強力な typedef (boost にはバージョンがあります) を使用し、<< 呼び出し中にその型にキャストします。その型の << をオーバーライドします。
のバリエーションに対して << をオーバーライドする必要がある場合complex<T>
、人生は難しくなります。
ここでの同じ質問に対する私の答え: c++ display complex number with i in imaginary partstd::
は、テンプレートの特殊化を名前空間に挿入するため、将来の非互換性のリスクを犠牲にして、必要な動作を生成します。
それを行うための本当にきちんとした方法はありません。私の提案は、iostream を捨てて、代わりにもっと C に似たものを書くことです。おそらく、書き込みが速く、読み取りが速く、実行が速くなります。