Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用共享ptr提高λ_C++_Boost Lambda - Fatal编程技术网

C++ 使用共享ptr提高λ

C++ 使用共享ptr提高λ,c++,boost-lambda,C++,Boost Lambda,如果我有一个称为base的多态基类,以及从base继承的类Derived1和Derived2。然后,我可以使用boost::lambda创建各种工厂。比如: typedef boost::function<Base *()> Creator; std::map<std::string,Creator> map1; map1["Derived1"] = boost::lambda::new_ptr<Derived1>(); map1["Derived2"] =

如果我有一个称为base的多态基类,以及从base继承的类Derived1和Derived2。然后,我可以使用boost::lambda创建各种工厂。比如:

typedef boost::function<Base *()> Creator;
std::map<std::string,Creator> map1;
map1["Derived1"] = boost::lambda::new_ptr<Derived1>();
map1["Derived2"] = boost::lambda::new_ptr<Derived2>();
typedef boost::函数创建者;
地图地图1;
map1[“Derived1”]=boost::lambda::new_ptr();
map1[“Derived2”]=boost::lambda::new_ptr();
(这不是真正的代码,我只是想说明问题。)

这是可行的,因此我可以使用字符串在映射中进行查找,然后调用lambda函数来实例化该类。一切都好

问题是它处理的是原始指针,我更喜欢使用智能指针(std::shared_ptr)

因此,如果我从:

typedef boost::function<Base *>() Creator;
typedef boost::function()创建者;
致:

typedef boost::function()创建者;
那我就被困在这里了。我曾尝试将boost::lambda::bind与boost::lambda::new_ptr结合使用,但运气不好,无法克服编译错误。(大量模板相关错误输出。)

我已经检查了StackOverflow中的其他类似消息,但是如果我尝试应用它的解决方案,就会出现上面提到的模板错误

如果有帮助的话,我很乐意提供示例代码和实际错误,但希望上面的信息足够了。我在GCC4.6上使用Boost1.47.0,在Fedora15上使用4.7Snapshot
class Base { 
public:
    virtual ~Base() = 0;
};
Base::~Base() {}

class Derived1 : public Base {};
class Derived2 : public Base {};

typedef boost::shared_ptr<Base> BasePtr;

typedef boost::function<BasePtr()> Creator;
template <typename T>
Creator MakeFactory()
{
    namespace la = boost::lambda;
    return la::bind( 
        la::constructor<BasePtr>(), 
        la::bind(la::new_ptr<T>()));
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::map<std::string,Creator> map1;    
    map1["Derived1"] = MakeFactory<Derived1>();
    map1["Derived2"] = MakeFactory<Derived2>();
    BasePtr p1 = map1["Derived1"]();
    BasePtr p2 = map1["Derived2"]();

    return 0;
}
公众: virtual~Base()=0; }; Base::~Base(){} 类Derived1:公共基{}; 类Derived2:公共基{}; typedef boost::shared_ptr BasePtr; typedef boost::函数创建者; 模板 创建者MakeFactory() { 名称空间la=boost::lambda; 返回la::bind( la::构造函数(), la::bind(la::new_ptr()); } int _tmain(int argc,_TCHAR*argv[] { 地图地图1; map1[“Derived1”]=MakeFactory(); map1[“Derived2”]=MakeFactory(); BasePtr p1=map1[“Derived1”](); BasePtr p2=map1[“Derived2”](); 返回0; } 然而,既然你能写,为什么还要麻烦呢

template <typename T>
BasePtr MakeFactoryImpl()
{
    return BasePtr(new T());
}
template <typename T>
Creator MakeFactory()
{
    return Creator(&MakeFactoryImpl<T>);
}
模板
BasePtr MakeFactoryImpl()
{
返回BasePtr(新的T());
}
模板
创建者MakeFactory()
{
返回创建者(&MakeFactoryImpl);
}

这是一个常见问题。两种类型是相关的(在您的例子中是通过继承)并不意味着模板的实例化与这两种类型保持相同的关系

解决方案是始终返回
shared\u ptr
,因为它可以保存指向
Base
的两个指针或任何派生类型,这将在语义上与当前版本兼容(即,在这两个版本中,调用者都会获得指向
Base
的(智能)指针)


另一方面,我会避免从工厂返回
shared_ptr
,因为您将智能指针的选择强加给所有用户。我更愿意返回原始指针(用户可以选择,但在某些情况下是危险的)或者一个
唯一的\u ptr
或者甚至
自动\u ptr
,它们是安全的,并且仍然允许用户选择不同的机制(即,如果您的函数返回一个
自动\u ptr
,用户仍然可以通过执行
共享的\u ptr p(f().release();
,而相反的操作是不可能的)(由
共享\u ptr
管理的内存无法释放以在不同的智能指针中使用。

此快速脏返回类型适配器不仅适用于将返回类型从
派生*
转换为
基*
,而且适用于任何可转换类型之间。为简单起见,函数对象不带参数。使用C++11变量adic模板—添加任意参数处理应该很容易。请随意以任何方式对此进行改进

template <typename ToType>
class return_type_adapter
{    
    template <typename toType>
    class return_type_adapter_impl_base
    {
      public:
        virtual toType call() = 0;
    };

    template <typename toType, typename Func>
    class return_type_adapter_impl : public return_type_adapter_impl_base<toType>
    {
      public:
        return_type_adapter_impl (Func func) : func(func) {}
        toType call() { return toType(func()); }
      private:
        Func func;
    };

    boost::shared_ptr<return_type_adapter_impl_base<ToType> > impl_base;

  public:
    ToType operator() () { return impl_base->call(); }

    template <typename Func>
    return_type_adapter (Func func) :
        impl_base(new return_type_adapter_impl<ToType, Func>(func)) {}
};
模板
类返回类型适配器
{    
模板
类返回\u类型\u适配器\u impl\u基
{
公众:
虚拟toType调用()=0;
};
模板
类return\u type\u adapter\u impl:public return\u type\u adapter\u impl\u base
{
公众:
返回\u类型\u适配器\u impl(Func Func):Func(Func){
toType调用(){return toType(func());}
私人:
Func Func;
};
boost::共享的ptr impl_base;
公众:
ToType运算符()({return impl_base->call();}
模板
返回类型适配器(Func Func):
impl_base(新返回类型适配器)impl(func)){
};
map1[“Derived1”]=boost::lambda::bind(
boost::lambda::构造函数(),
boost::lambda::bind(
boost::lambda::new_ptr());
map1[“Derived2”]=boost::lambda::bind(
boost::lambda::构造函数(),
boost::lambda::bind(
boost::lambda::new_ptr());
但老实说,这是一个复杂的级别,再使用boost lambda真的没有意义。一个更简单的解决方案:

template<typename DerivedType>
boost::shared_ptr<Base> makeDerived() {
    return boost::shared_ptr<Base>(new DerivedType);
}
[...]

    map1["Derived1"] = makeDerived<Derived1>;
    map1["Derived2"] = makeDerived<Derived2>;
模板
boost::shared_ptr makeDerived(){
返回boost::shared_ptr(新的DerivedType);
}
[...]
map1[“Derived1”]=makeDerived;
map1[“Derived2”]=makeDerived;

关于将智能指针实现的选择强加给用户,这是一个有趣的观点,我没有考虑到这一点。
map1["Derived1"] = boost::lambda::bind(
    boost::lambda::constructor<boost::shared_ptr<Base>>(),
    boost::lambda::bind(
        boost::lambda::new_ptr<Derived1>()));
map1["Derived2"] = boost::lambda::bind(
    boost::lambda::constructor<boost::shared_ptr<Base>>(),
    boost::lambda::bind(
        boost::lambda::new_ptr<Derived2>()));
template<typename DerivedType>
boost::shared_ptr<Base> makeDerived() {
    return boost::shared_ptr<Base>(new DerivedType);
}
[...]

    map1["Derived1"] = makeDerived<Derived1>;
    map1["Derived2"] = makeDerived<Derived2>;