2015-04-08 4 views
2
#include <memory> 
#include <iostream> 
#include <exception> 
#include <curl/curl.h> 

class client 
{ 
private: 
    std::unique_ptr<CURL, decltype(&psclient::del_curl)> uptr_curl_; 

    inline CURL * init_curl() 
    { 
     CURLcode result = curl_global_init(CURL_GLOBAL_DEFAULT); 
     if(result != CURLE_OK) 
      throw std::logic_error(curl_easy_strerror(result)); 
     return curl_easy_init(); 
    } 

    inline void del_curl(CURL * ptr_curl) 
    { 
     curl_easy_cleanup(ptr_curl); 
     curl_global_cleanup(); 
    } 
public: 
    inline client() 
    : uptr_curl_(init_curl(), &client::del_curl) 
    { 
    } 
} 

Компилятор продолжает жаловаться No matching constructor for initialization of 'std::unique_ptr<CURL, void (*)(CURL *)>'Как передать нестатические функции члена как unique_ptr Deleter

Мне кажется, как декларация является правильной для шаблона Deleter аргумента. Это указатель на функцию, который возвращает void и принимает CURL * в качестве аргумента. Это соответствует сигнатуре del_curl.

Есть ли еще одно случайное правило, неизвестное мне, в C++, которое указывает требование для аргументов шаблона к нестационарным указателям на функцию-член? Если да, то почему?

+2

Изменение 'недействительным del_curl (CURL * ptr_curl)' от нестатической функции члена к статической функции-члена. –

+0

ПОЧЕМУ ПОЧЕМУ ПОЧЕМУ :) –

+0

@FranciscoAguilera, потому что вы пытаетесь привязать указатель-к-функции к функции-указателю-члену, и это не работает: 'uptr_curl_ (init_curl(), & client :: del_curl) ' – vsoftco

ответ

5

Ответ @R. Саху верно имо. Однако, если вы настаиваете прохождения нестатических функций члена Deleter, вот способ сделать это, используя старый добрый std::bind и std::function:

#include <memory> 
#include <iostream> 
#include <functional> 

class Foo 
{ 
private: 
    std::unique_ptr<int, std::function<void(int*)>> _up; 
public: 
    Foo(): _up(new int[42], std::bind(&Foo::deleter, this, std::placeholders::_1)) 
    { 

    } 
    void deleter(int* p) 
    { 
     delete[] p; 
     std::cout << "In deleter" << std::endl; 
    } 
}; 

int main() 
{ 
    Foo foo; 
} 

PS: Я просто не нравлюсь bind, интересно если можно это улучшить.


С лямбда:

Foo(): _up(new int[42], 
       [this](int* p)->void 
       { 
        deleter(p); 
       } 
     ){} 
+0

Вы правы, это правильно, в тех случаях, когда вы хотите «передать статическую функцию-член как деблокировать unique_ptr», но мой вопрос: «Как передать нестационарную функцию-член как деблокировать unique_ptr». –

+0

Upticked. Я собирался опубликовать вполне буквально идентичный код. Спасибо, что спас меня. = P – WhozCraig

+1

@FranciscoAguilera 'deleter' здесь нестатический. – vsoftco

2

Второй параметр шаблон, используемый в объявлении uptr_curl_ является void (*)(CURL *)

Тип &client::del_curl является void (CURL::*)(CURL*).

Это не то же самое. Вы можете изменить del_curl на функцию члена static. Это решит проблему.

Update

Вы можете использовать не функцию static члена с помощью std::function и std::bind.

class client 
{ 
    public: 
     client(); 
    private: 
     std::unique_ptr<CURL, std::function<void(CURL *)>> uptr_curl_; 
     CURL * init_curl(); 
     void del_curl(CURL * ptr_curl); 
}; 

client::client() : uptr_curl_(init_curl(), 
           std::bind(&client::del_curl, this, std::placeholders::_1)) 
{ 
    // ... 
} 
+0

Действительно, я думаю, что также интересно сказать, можно ли использовать нестационарную функцию-член как делеттер. Можете ли вы каким-то образом использовать 'std :: function' вместо этого? – vsoftco

+0

Нет, вы ошибаетесь. Тип 'client :: del_curl' -' void (psclient :: *) (void *) '. См. Мое редактирование. –

+0

Есть еще одна причина, по которой вы не можете передавать нестатические функции-члены в качестве аргументов-делетеров, и я хочу знать ПОЧЕМУ. @vsoftco Это был оригинальный вопрос. Никто не читает до конца. xD –

Смежные вопросы