7
std::vector<std::complex<float> > c;
std::vector<float> d;
std::transform(c.begin(), c.end(), d.begin(), std::real<float>);

オーバーロードされた関数からコンパイラがアドレスを解決できなかったのはなぜreal<float>ですか?

コンパイラが意味するオーバーロードされた関数はどれですか?

4

2 に答える 2

5

ライブラリの実装により、 に追加のオーバーロードが提供されましstd::real<float>た。

なぜオーバーロード?

26.4.9 追加のオーバーロード [cmlx.over]

  • 1 次の関数テンプレートには、追加のオーバーロードがあります。

    arg norm
    conj proj
    imag real
    
  • 2 追加の過負荷は、以下を確保するのに十分でなければならない:
    1. 引数の型が の場合、long double効果的に にキャストされcomplex<long double>ます。
    2. それ以外の場合、引数が型doubleまたは整数型の場合、事実上 にキャストされcomplex<double>ます。
    3. それ以外の場合、引数の型が であれば、float効果的に にキャストされcomplex<float>ます。

[...]

問題の解決策:

に基づいて範囲を使用することができます...

for (auto v : c) d.push_back(real(v));

real... または呼び出しをファンクターまたは別の関数にパックします ...

struct my_caller {
    template <typename T> T operator() (std::complex<T> const &c) {
        return real(c);
    }
};

...またはメンバー関数を使用...

std::transform(c.begin(), c.end(), d.begin(), [](std::complex<T> const &c) { 
    return c.real();
});

重要:

を使用する場合は、ターゲットに十分なスペースが必要であることに注意してくださいtransform

std::vector<float> d (c.size());

またはバックインサーターを使用します。

std::transform(c.begin(), c.end(), back_inserter(d), ...);

そうしないと、未定義のメモリを反復処理し、未定義の動作が発生します。

于 2013-04-03T06:40:05.887 に答える