2017-12-01 18 views
0

私は動きと左辺のセマンティクスでかなり新しいです。そして私はそれが間違っている印象を持っています。ここで 私は一度FunctContainerを書くことができるようにしたいコードが実装されていますfc1に保存されている機能の寿命がfの1、寿命であるようにlvalueの場合は参照をとり、rvalueの場合はコピーを作成します。つまり、rvalueを永続化します。

std::function<double(double)> f = [](double x){return (x * x - 1); }; 

FunctContainer fc1 = FunctContainer(f); 

FunctContainer fc2 = FunctContainer([](double x){return (x * x - 1); }); 

私はFunctContainer年代のctorsを書きたいです含まれている機能のfc2は、fc2の寿命です。

私は何かを書きましたが(下記参照)、私は本当に満足していません(私は間違っています)。

これは正しいですが、f_がrvalueのときにコンストラクタを呼び出した後にf_が期限切れになります。

class FunctContainerWRONG{ 
public: 
    IntegrandNotProjecting(const std::function<double(double)>& function) 
    : f_(function){} 
    IntegrandNotProjecting(const std::function<double(double)>&& function) 
    : f_(std::move(function)){} 
    const std::function<double(double)>& f_; 
private: 
}; 

これは私にひどい見て、おそらく正しいC++ではないが、所望の動作がどのように見えるかを擬似コードで説明することを意図しています。私はブランドの新しいオブジェクトをconstuctしないようにしたいと私はちょうど私のオブジェクトをできるようにしたいことができた場合は、「持続」:

class FunctContainer{ 
public: 
    FunctContainer(const std::function<double(double)>& function) 
    : f_p(nullptr), 
     f_(function){} 
    FunctContainer(const std::function<double(double)>&& function) 
    : f_p()std::make_shared<std::function<double(double)>>(function)), 
     f_(*f_p){} 
private: 
    std::shared_ptr<std::function<double(double)>> f_p; 
    const std::function<double(double)>& f_; 
}; 
+0

だから、(一貫性のない所有権と寿命管理のほかに)最後の例で、実際に何が間違っていますか?所有権はとにかく共有されていないので、 'unique_ptr'を使うことができます。 – VTT

+0

@VTT最後の例で本当に好きでないのは、関数がrvalueならコピーを作成したいと言っていますが、むしろ最適化するためにコンパイラに明示的に伝えたいと思うという事実です。さらに、私が右辺値を持ち、他の場合に共有されている場合は、ポインタが一意でなければならないことを指摘しています。これは、もう1つのポインタが必要であり、これらのポインタを管理することを意味します。 – jimifiki

答えて

1

フォワーディング参照、あなたは簡単にこれを達成するのを助けることができルールを崩壊参照を。

template <typename T> 
struct FunctContainer 
{ 
    T _f; 

    template <typename TFwd> 
    FunctContainer(TFwd&& f) : _f{std::forward<TFwd>(f)} { } 
}; 

template <typename T> 
auto makeFunctContainer(T&& f) -> FunctContainer<T> 
{ 
    return {std::forward<T>(f)}; 
} 
  • あなたは左辺値makeFunctContainerを起動すると、T左辺値参照になります。つまり、左値参照FucntContainerに保存します。あなたは右辺値makeFunctContainerを呼び出すと

  • Tになります。つまり、FucntContainerに保存します。


使用例:

auto fc0 = makeFunctContainer(std::move(f0)); // `fc0` owns `f0` 
auto fc1 = makeFunctContainer(f1); // `fc1` stores a reference to `f1` 
関連する問題