2017-01-17 8 views
3

Я тестирую пользовательские удалители для unique_ptr. Странно, только удаленные объекты, которые являются объектами функции, работают нормально. Если я заменяю их функциями или лямбдами, программа не компилируется. Что я делаю неправильно?Как использовать lambdas и выполняет функции пользовательских удалений для unique_ptr

Вот моя полная программа испытаний

#include <iostream> 
#include <memory> 

using namespace std; 


class Vehicle { 
public: 
    Vehicle(){ cout<<"Vehicle constructor..."<<endl;} 
    virtual ~Vehicle(){cout<<"~Vehicle destructor..."<<endl;} 
    virtual void go()=0; 
}; 

class Car:public Vehicle { 
    public: 
    void go() override { 
     cout<<"Going by car..."<<endl; 
    } 
}; 

class Bicycle:public Vehicle { 
    public: 
    void go() override { 
     cout<<"Going by bicycle..."<<endl; 
    } 
}; 

// Custom deleters 
auto CustomLambdaDeleter = [](Vehicle* v){ 
    cout<<"Custom lambda deleter called..."<<endl; 
    delete v; 
}; 

void CustomFunctionDeleter(Vehicle* v){ 
    cout<<"Custom function deleter called..."<<endl; 
    delete v; 
} 

struct CustomFunctorDeleter 
{ 
    void operator()(Vehicle* v) const { 
     cout<<"Custom functor deleter called..."<<endl; 
     delete v; 
    } 
}; 


// Doesn't compile 
//using VehiclePtr = unique_ptr<Vehicle, decltype(CustomLambdaDeleter)>; 
// Doesn't compile 
//using VehiclePtr = unique_ptr<Vehicle, decltype(&CustomFunctionDeleter)>; 
// Works ok 
using VehiclePtr = unique_ptr<Vehicle, CustomFunctorDeleter>; 


class VehicleFactory { 
public: 
    static VehiclePtr createVehicle(string type){ 
     VehiclePtr vptr; 
     if("bicycle"==type) { 
      vptr.reset(new Bicycle()); 
      // This also works 
      // vptr= (VehiclePtr) new Bicycle(); 
      return vptr; 
     } 
     else if("car"==type) { 

      vptr.reset(new Car()); 
      return vptr; 
     } 

     return nullptr; 
    } 
}; 


void vehicleFactoryTest(){ 
    cout<<"* Starting vehicleFactoryTest()..."<<endl; 
    auto firstVehicle = VehicleFactory::createVehicle("bicycle"); 
    firstVehicle->go(); 
    auto newCar = VehicleFactory::createVehicle("car"); 
    newCar->go(); 
} 

int main(int, char **) 
{ 

    vehicleFactoryTest(); 
    return 0; 
} 
+0

Чтобы помочь людям ответить на ваш вопрос, вам нужно быть более конкретным относительно ошибки. Пожалуйста, отредактируйте свое сообщение, чтобы включить точные ошибки, которые вы получаете от вашего [mcve] (желательно использовать copy + paste, чтобы избежать ошибок транскрипции). –

+0

Я получаю следующее сообщение об ошибке: использование удаленной функции ' :: ()' – Fedorov7890

ответ

5

Проблема не с одной из

using VehiclePtr = unique_ptr<Vehicle, decltype(CustomLambdaDeleter)>; 

или

using VehiclePtr = unique_ptr<Vehicle, CustomFunctorDeleter>; 

Те две компиляции сами по себе. Проблема заключается в следующей строке в createVehicle

VehiclePtr vptr; 

Здесь вы по умолчанию построения unique_ptr, который не будет компилировать в случае лямбда Deleter, потому что лямбды не по умолчанию конструктивны. Так что вам нужно

VehiclePtr vptr{nullptr, CustomLambdaDeleter}; 

В случае, когда вы используете указатель на функцию, вы пытаетесь по умолчанию построить unique_ptr с nullptr Deleter, который не допускается. Исправление аналогично, вам нужно передать указатель на функцию в этом случае.

VehiclePtr vptr{nullptr, CustomFunctionDeleter}; 

Вы также сделать подобную ошибку в заключительном заявлении в обратном createVehicle. Измените эту строку на

return vptr; 
+0

@ Fedorov7890 Обновлено. В вашем возвратном выражении произошла другая ошибка. Если у вас все еще есть проблемы, используйте онлайн-компилятор и вставьте ссылку на пример, который не будет компилироваться. – Praetorian

+0

Спасибо, изменение от 'return nullptr' до 'return vptr' устранило проблему. – Fedorov7890