5

大きなシーケンスの2つのベクトルを持つクラスを設計しようとしています。

std::vector<double> factory() {
    return std::vector<double>{1,2,3}; // it actually generates a large sequence of double
}

struct my_class {
    my_class(const std::vector<double>& x, const std::vector<double>& y)
     : m_x(x), m_y(y)
    { }

    std::vector<double> m_x;
    std::vector<double> m_y;
};

int main() {
    my_class c(factory(), factory());
    my_class c2(factory(), {0.5, 1, 1.5});
}

まあ、それはうまく機能しますが、vectorのmoveコンストラクターを使用しません。そこで、完全な転送でr値参照を受け入れるようにコンストラクターを変更しようとしました。

struct my_class {
    template<typename X, typename Y>
    my_class(X&& x, Y&& y
             , typename std::enable_if<std::is_convertible<X, std::vector<double> >::value &&
                                       std::is_convertible<Y, std::vector<double> >::value>::type * = 0
            )
     : m_x(std::forward<X>(x)), m_y(std::forward<Y>(y))
    { }

    std::vector<double> m_x;
    std::vector<double> m_y;
};

そして今、私は問題を抱えています。initializer_listを使用してインスタンスを作成しようとすると、次のようなエラーが発生しました。

$ g++ -W -Wall -std=gnu++0x a.cpp
a.cpp: In function ‘int main()’:
a.cpp:34:32: error: no matching function for call to ‘my_class::my_class(std::vector<double>, <brace-enclosed initializer list>)’
a.cpp:17:18: note: candidate is: my_class::my_class(const my_class&)

std::initializer_list<double>これはに変換できないかもしれないと思いましたstd::vector<double>が、実際には変換可能であり、enable_if引数なしで試したときに同じエラーが発生しました。私は何かが足りないのですか?

4

1 に答える 1

7

推奨されるイディオムは、値を渡し、メンバー初期化子リスト内を手動で移動することです。

struct my_class {
    my_class(std::vector<double> x, std::vector<double> y)
     : m_x(std::move(x)), m_y(std::move(y))
    { }

    std::vector<double> m_x;
    std::vector<double> m_y;
};

これは、考えられるすべての引数で機能し、かなり高速です。

  • ベクトルlvalueを渡すと、ベクトルは にコピーされてxから に移動されm_xます。
  • ベクトルrvalueを渡すと、ベクトルは に移動されx、再び に移動されm_xます。
  • 初期化子リストを渡すxと、そのリストから初期化されてから に移動されm_xます。

別の方法として完全転送がありますが、これにより、クライアントが何を渡すかを知ることが難しくなります。

struct my_class {
    template<typename T, typename U>
    my_class(T&& x, U&& y)
     : m_x(std::forward<T>(x)), m_y(std::forward<U>(y))
    { }

    std::vector<double> m_x;
    std::vector<double> m_y;
};

また、g++ で大量の警告が表示されるので、お勧めしません。完全を期すために言及するだけです。

于 2011-11-05T09:29:59.273 に答える