2014-10-21 158 views
1

我有一個類創建一個包裝函數來處理一個weak_ptr對象。當函子執行時,它將在調用對象函子之前測試weak_ptr。std :: bind和std :: weak_ptr

此外,如果對象不再存在,則包裝函子可以返回默認值。

這是在GCC 4.4.7編譯的類的摘錄...

class Bind 
{ 
public: 

    // non-void weak-functor 
    template <typename R> 
    struct Wrapper<R, typename std::enable_if<!std::is_void<R>::value>::type> 
    { 
     using result_type = R; 

     template <typename O> 
     R operator()(const std::weak_ptr<O> && obj, 
        std::function<R()> && func, R && ret) 
     { 
      if (auto ptr = obj.lock()) 
      { 
       return func(); 
      } 

      return std::forward<R>(ret); 
     } 
    }; 

    // weak from shared - non-void return 
    template <typename R, typename F, typename O, typename... A> 
    static std::function<R()> Weak(R && ret, 
            F func, 
            const std::shared_ptr<O> && obj, 
            A&&... args) 
    { 
     return std::bind(Wrapper<R>(), 
         std::weak_ptr<O>(obj), 
         std::function<R()>(std::bind(func, obj.get(), 
              std::forward<A>(args)...)), 
         ret); 
    } 

    // ... 
}; 

類可以使用這樣的...

auto x = std::make_shared<X>(); 
auto f = Bind::Weak(false, &X::foo, x, 1, 2, 3); 

f(); // returns x::foo(1, 2, 3) 

x.reset() 

f(); // returns false 

不幸的是,升級後編譯器到GCC 4.8.3不再編譯。錯誤就像這樣開始...

error: could not convert 'std::bind(_Func&&, _BoundArgs&& ...) 

...與平常的山脈模板crud。 jist是它不能再將Bind :: Weak()中的std :: bind()的結果轉換爲Bind :: Weak()的返回類型。

我已經擺弄了幾個小時,現在還沒有能夠解決這個問題。

+1

你[濫用'std :: forward'](http://stackoverflow.com/a/13219621/596781)。 – 2014-10-21 22:52:54

+0

'x'不是一個右值,因此似乎不太可能綁定到'Bind :: Weak'中的右值引用'obj'。 – 2014-10-21 22:54:50

回答

1

問題是你不能使用std::function做完美的轉發,因爲std::function必須是可複製的,所以綁定值也必須是可複製的。

改變operator()原型:

template<typename O> 
R operator()(const std::weak_ptr<O>& obj, const std::function<R()>& func, const R& ret) 
{ 
    //... 
} 

應該或多或少足以使這項工作(這是很難確定,因爲你貼的代碼是不完整)。

但是現在您的轉發到綁定被破壞,所有那些std::forward&&沒有太大意義,IMO。

+0

就是這樣。非常感謝。 – user1715664 2014-10-22 12:34:39

相關問題