2012-07-15 4 views
8

ファンクタを引数として使用してファンクタを呼び出し、その戻り値をboost::shared_ptr"<class name>はコール演算子を提供していません"関数の戻り値をラップするときにエラーが発生しました

以下はコンパイルを拒否し、私はすべてのアイデアがありません。私は "std :: vector < std :: string>はコールオペレータを提供しません"(おおよそ)。

make_shared< packaged_task< boost::shared_ptr< std::vector<std::string> > > >(
    bind(ReturnValueAsShared< std::vector<std::string> >, 
     bind([a function that returns a std::vector<std::string>]))); 

EDIT:私はこれは私がそれを使用しようとしているれている文脈ではMac OS Xの

template< typename T > 
boost::shared_ptr<T> ReturnValueAsShared(
    boost::function< T() > func) 
{ 
    return boost::make_shared<T>(func()); 
} 

にクラン3.1を使用しています。ここの完全な自己完結型のテストケースがあります。このコードは、同じエラーでコンパイルに失敗し、私の人生のために私が間違っているものを見ることができません。

#include <boost/make_shared.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/function.hpp> 
#include <boost/bind.hpp> 

#include <string> 
#include <vector> 

std::vector<std::string> foo(std::string a) 
{ 
    std::vector<std::string> vec; 
    vec.push_back(a); 
    return vec; 
} 

template< typename T > 
boost::shared_ptr<T> ReturnValueAsShared(
    boost::function< T() > func) 
{ 
    return boost::make_shared<T>(func()); 
} 

int main() 
{ 
    auto f = boost::bind(ReturnValueAsShared< std::vector<std::string> >, 
         boost::bind(foo, std::string("a"))); 
    f(); 

} // main 

そして、ここでエラー出力です:ここで

In file included from testcase.cpp:3: 
In file included from /usr/local/include/boost/function.hpp:64: 
In file included from /usr/local/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:47: 
In file included from /usr/local/include/boost/function/detail/function_iterate.hpp:14: 
In file included from /usr/local/include/boost/function/detail/maybe_include.hpp:13: 
/usr/local/include/boost/function/function_template.hpp:132:18: error: type 'std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >' does not provide a call operator 
      return (*f)(BOOST_FUNCTION_ARGS); 
       ^~~~ 
/usr/local/include/boost/function/function_template.hpp:907:53: note: in instantiation of member function 'boost::detail::function::function_obj_invoker0<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >, std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > >::invoke' requested here 
     { { &manager_type::manage }, &invoker_type::invoke }; 
                ^
/usr/local/include/boost/function/function_template.hpp:722:13: note: in instantiation of function template specialization 'boost::function0<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > >::assign_to<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > >' requested here 
     this->assign_to(f); 
      ^
/usr/local/include/boost/function/function_template.hpp:1042:5: note: in instantiation of function template specialization 'boost::function0<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > >::function0<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > >' requested here 
    base_type(f) 
    ^
/usr/local/include/boost/bind/bind.hpp:243:43: note: in instantiation of function template specialization 'boost::function<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >()>::function<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > >' requested here 
     return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_]); 
             ^
/usr/local/include/boost/bind/bind_template.hpp:20:27: note: in instantiation of function template specialization 'boost::_bi::list1<boost::_bi::bind_t<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >, std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > (*)(std::basic_string<char>), boost::_bi::list1<boost::_bi::value<std::basic_string<char> > > > >::operator()<boost::shared_ptr<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > >, boost::shared_ptr<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > > (*)(boost::function<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >()>), boost::_bi::list0>' requested here 
     BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0); 
         ^
testcase.cpp:27:4: note: in instantiation of member function 'boost::_bi::bind_t<boost::shared_ptr<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > >, boost::shared_ptr<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > > (*)(boost::function<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >()>), boost::_bi::list1<boost::_bi::bind_t<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >, std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > (*)(std::basic_string<char>), boost::_bi::list1<boost::_bi::value<std::basic_string<char> > > > > >::operator()' requested here 
    f(); 
^
1 error generated. 

は、いくつかのより多くの手がかりです。次のコードはうまくコンパイルが、これは私が:)

#include <boost/make_shared.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/function.hpp> 
#include <boost/bind.hpp> 

#include <string> 
#include <vector> 

std::vector<std::string> foo() 
{ 
    std::vector<std::string> vec; 
    return vec; 
} 

template< typename T > 
boost::shared_ptr<T> ReturnValueAsShared(
    boost::function< T() > func) 
{ 
    return boost::make_shared<T>(func()); 
} 

int main() 
{ 
    auto f = boost::bind(ReturnValueAsShared< std::vector<std::string> >, 
         foo); 
    f(); 

} // main 
+3

問題を簡素化し、最小限の(非)動作のサンプルコードを提供してください。 –

+0

エラーは何ですか? –

+0

@KerrekSB 'ReturnValueAsShared >'として使用しようとすると、エラーは 'std :: vector は呼び出し演算子を提供しません。 – Lucas

答えて

2

いくつかの構造(のようなbind)は、あなたが実際に鼻の上にキャプチャしたくない中間の「表現」のタイプを返します。その場合、タイプをautoで取得してはならず、明示的な変換を指定する必要があります。そうしないと、一意の単一のユーザー定義変換チェーンが存在しないためです。あなたのケースでは、functionにバインド式から明示的な変換を追加します。

typedef std::vector<std::string> G; 
auto f = boost::bind(ReturnValueAsShared<G>, 
      static_cast<boost::function<G()>(boost::bind(foo, std::string("a"))) 
        ); 

(これ自体は、実際に私のために動作しませんが、あなたが対応するstd construc ­ションを使用している場合、それは動作しません。)

int main() 
{ 
    auto f = boost::bind(ReturnValueAsShared< std::vector<std::string> >, 
         boost::protect(boost::bind(foo, std::string("a")))); 
    f(); 

} // main 

これはそれを得ることができる限りクリーンである:

+0

キャスト 'boost :: function (...)'を使って2番目の 'bind'呼び出しをラップするとすべてが正しく機能します。情報をありがとう。 – Lucas

2

完全な書き換えをしたいコードではありませんので、それは私を助けていない、オリジナルの答えは間違っていました。

エラー解析

私はここで間違って何が起こっていたか、最初は知らなかったとして、私はいくつかの分析を行いました。私は将来の参照のためにそれを保持しています。問題を回避する方法については、以下の解決策を参照してください。

bind.hppはこの行います

私の意見では、このように変換し
return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_]); 

unwrapper<F>::unwrap(f, 0) = ReturnValueAsShared< std::vector<std::string> > 
base_type::a1_ = boost::bind(foo, std::string("a")) 

だから行うには、このコードは、関数に引数を渡すだけの方法で期待するものそうです。しかし、これが機能するには、式a[base_type::a1_]はタイプboots:_bi::value<T>でなければなりませんが、アンラップタイプboost::_bi::bind_tです。代わりに引数として渡されるファンクタのだから、特別なオーバーロードされたバージョンが呼び出されます:

namespace boost { namespace _bi { class list0 { 
    … 
    template<class R, class F, class L> 
    typename result_traits<R, F>::type 
    operator[] (bind_t<R, F, L> & b) const { 
     return b.eval(*this); 
    } 
    … 
} } } 

これは代わりにそれを渡すので、引数なしの関数を評価します。したがって、ベクトルを返すオブジェクトの代わりに、引数は今vecotrです。それ以降の手順では、それをboost::functionに変換して失敗します。

Canonicalのソリューション

まだ再編集:
nested bindsのこの特別な処理が機能として意図されているように見えます。ユーザーZaoとhellerと#boostと話すと、私は今これらの影響に対処するためにprotect関数があることを知っています。だから、この問題に対する標準的な解決策は、次のように表示されます。

… 
#include <boost/bind/protect.hpp> 
… 
    auto f = boost::bind(ReturnValueAsShared< std::vector<std::string> >, 
    boost::protect (boost::bind(foo, std::string("a")))); 
… 
+0

いいえ、戻り値は、実行時に 'shared_ptr'を返すファンクタです。私が 'f()'を '(* f)()'に置き換えると、 'f'がポインタ型ではないと言うコンパイラエラーが発生します。 – Lucas

+0

OK、あなたは緊張している、問題は一層深いです。 'bind'には' shared_ptr'のオーバーロードがないので、デフォルトでは関数オブジェクトが仮定されています。しかし、 'shared_ptr'は呼び出し演算子を提供しないので、何かが失敗します。 – MvG

+0

うん、 'bind'は' shared_ptr'のためにオーバーロードを必要としません、それはテンプレートです。また、このエラーは、 'vector 'に 'shared_ptr'ではなく、呼び出し演算子がないことを告げるものです。 – Lucas

3

ブースト::守るには、移動するための方法です。

+1

この回答は、 'boost :: protect'が何であるか、それが何であるか、おそらくそれをより詳細に記述するドキュメントへのリンクによって説明することができます。 – Lucas

関連する問題