4

古いコードで C++10 の新機能を利用しているときに、make_shared12 個のパラメーターを使用して呼び出すことができないという問題が発生しました。make_sharedMicrosoft の STL で、エミュレーションをどのように使用しているか、10 が最大であると話しているのを覚えています。明らかに、これのためだけにコードをリファクタリングすることは問題外なので、基本的に私の質問はmake_shared、VS 2010 で10 個を超えるパラメーターを取得する方法はありますか?

4

2 に答える 2

11
make_shared<foobar>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);

で置き換えることができます

shared_ptr<foobar>(new foobar(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));

C++11 では、std::make_shared は実際には 2 番目の方法を使用してオブジェクトを作成するよりもパフォーマンスを最適化します。これは、メモリ割り当てを 2 つではなく 1 つしか実行しないためです。ただし、変数が 10 個を超えると、選択の余地はあまりありません。使用するものについて。

于 2013-01-18T00:12:51.450 に答える
1

make_sharedその効率的な利点を本当に使用したい場合でも、そうすることができます:

#include <tuple>
#include <memory>
#include <redi/index_tuple.h>

template<typename X, typename... Args>
  std::shared_ptr<X>
  make_shared_TO_THE_MAX(Args&&... args)
  {
    struct Wrapper
    {
      X x;

      template<typename... T>
        Wrapper(std::tuple<T...> targs) : Wrapper(targs, to_index_tuple<T...>{}) { }

      template<typename T, unsigned... I>
        Wrapper(T targs, index_tuple<I...>) : x(std::get<I>(targs)) { }
    };

    auto wrapped = std::make_shared<Wrapper>(std::forward_as_tuple(std::forward<Args>(args)...));
    return std::shared_ptr<X>(wrapped, &wrapped->x);
  }

これにより、コンストラクターの引数が参照のタプルにまとめられ、それが に渡されます。1 つしか取得できないため、10 個の引数を処理できなくmake_sharedても問題ありません。which を使用するmake_shared代わりに、 ( type のメンバーと同じサイズとレイアウトである) a にスペースを割り当て、引数タプルで構築します。コンストラクターは、タプルを展開してコンストラクターに渡す別のコンストラクターに委譲します。make_shared<X>make_shared<Wrapper>WrapperXWrapperX

最後に、shared_ptrエイリアシング コンストラクタを使用して、shared_ptr<X>と所有権を共有するが、オブジェクトshared_ptr<Wrapper>のアドレスを格納するを返します。X

<redi/index_tuple.h>私自身のヘッダーですが、C ++ 14用に標準化された同様のものを取得しようとしています。

これは可変個引数テンプレートなしでも実行できますが、より多くの作業が必要です。これは引数が 2 つの場合です。12 の場合はさらに 10 を追加してください。

#include <tuple>
#include <memory>

template<typename X, typename Arg0, typename Arg1>
  std::shared_ptr<X>
  make_shared_TO_THE_MAX(Arg0&& arg0, Arg1&& arg1)
  {
    struct Wrapper
    {
      X x;

      template<typename T0, typename T1>
        Wrapper(std::tuple<T0, T1> targs)
        : x(std::get<0>(targs), std::get<1>(targs)) { }
    };

    auto wrapped = std::make_shared<Wrapper>(std::forward_as_tuple(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1)));
    return std::shared_ptr<X>(wrapped, &wrapped->x);
  }
于 2013-01-20T12:21:49.197 に答える