8

Stroustrup の C++ ブックには、引数を取るカスタム マニピュレータの例があります (添付のコードを参照してください)。構造体の作成方法について混乱しています。特に、「smanip」のコンストラクターには 2 つの int 引数があるように見えます。1 つは関数ポインター「ff」用、もう 1 つは「ii」用です。次を使用して構造体を作成するために int 引数がどのように渡されるのかわかりません。

cout << setprecision(4) << angle;

さらに、これらの関数が呼び出される順序と、型引数 Ch および Tr はどのように決定されるのでしょうか? どうもありがとう。

// manipulator taking arguments
struct smanip{
    iso_base& (*f) (ios_base&, int);
    int i;
    smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){}
};

template<cladd Ch, class Tr>
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){
    return m.f(os, m.i);
}

ios_base& set_precision(ios_base& s, int n){
    return s.setprecision(n); // call the member function
}

inline smanip setprecision(int n){
    return smanip(set_precision,n);
}

// usage:
cout << setprecision(4) << angle;
4

2 に答える 2

9
setprecision(4)

通話

inline smanip setprecision(int n){
    return smanip(set_precision,n);
}

関数smanipへのポインタからを作成し、 .set_precisionn

struct smanip{
    ios_base& (*f) (ios_base&, int);
    int i;
    smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){}
};

smanip関数へのポインターと整数を保持する構造体です。その関数は、ios_base参照渡しとを受け取り、参照int渡しを返しますios_base

この時点で、行は事実上次のようになります。

smanip m(&setprecision, 4);
cout << m << (otherstuff);

これは、次のテンプレートに一致します。

template<class Ch, class Tr>
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){
    return m.f(os, m.i);
}

そして、コンパイラは、左側のストリームからCh、およびを推測できます。Trこの場合、std::cout. コードが実行されm.f(os, m.i)ます。これにより、 が保持する関数ポインタが呼び出され、 が保持smanipするストリームと整数が渡されsmanipます。

ios_base& set_precision(ios_base& s, int n){
    return s.setprecision(n); // call the member function
}

これは を呼び出しますcout.setprecision(n)

したがって、この行は次のように変換されます。

std::cout.setprecision(4) << angle;
于 2011-10-28T21:55:05.210 に答える
0

マニピュレーター ファンクターは、関数ポインターと int を引数として取り、後で使用するために両方を内部に格納します。読みやすくするために、コンストラクターのシグネチャを次の 2 つの宣言に分割できます。

typedef ios_base& (*f_ptr)(ios_base&,int);
smanip( f_ptr f, int )

つまり、最初の引数は関数ポインタで、2 番目の引数は値です。

サンプル コードの実行順序では、最初に関数setprecisionが呼び出され、その関数は関数ポインタと値をsmanipオブジェクト内に格納し、それを返します。オブジェクトは適切なoperator<<に渡され、引数を渡す現在のストリームで格納された関数ポインタを抽出して実行します。

// on the calling end
         setprecision(4)  // --> construct __s = smanip( set_precision, 4 )
(cout <<                ) // --> passes __s to `operator<<`
// inside operator<<
return m.f( os, m.i );    // calls: set_precision( os, 4 ) (m.f == &set_precision
                          //                                m.i == 4 )
于 2011-10-28T21:54:04.477 に答える