2016-10-03 2 views
2

Vous ne trouvez pas ce qui est le problème dans le code suivantstd :: unique_ptr avec lambda ne marche pas Deleter personnalisée compilation

std::unique_ptr<CFStringRef, std::function<void(CFStringRef)>> 
cfstr(CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8), 
           [](CFStringRef obj){ 
            CFRelease(obj); 
           }); 

CFStringCreateWithCString doit retourner type correct comme par CFStringCreateWithCString documentation

Erreur:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x c++ -arch x86_64 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=c++11 -stdlib=libc++ -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wno-unused-value -Wno-empty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-constant-conversion -Wno-int-conversion -Wno-bool-conversion -Wno-enum-conversion -Wno-shorten-64-to-32 -Wno-newline-eof -Wno-c++11-extensions -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -fasm-blocks -fstrict-aliasing -Wdeprecated-declarations -Winvalid-offsetof -mmacosx-version-min=10.7 -g -fvisibility-inlines-hidden -Wno-sign-conversion -D_DEBUG -DDEBUG -MMD -MT dependencies -MF -c DynamicStore.cpp -o DynamicStore.o 

DynamicStore.cpp:29:5: error: no matching constructor for initialization of 'std::unique_ptr<CFStringRef, std::function<void (CFStringRef)> >' 
    cfstr((CFStringRef)CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8), 

main.cpp:73:14: note: in instantiation of function template specialization 'std::__1::for_each<std::__1::__wrap_iter<const std::__1::sub_match<const char *> *>, (lambda at main.cpp:73:45)>' requested here 
     std::for_each(cm.begin(), cm.end(), [](const std::cmatch &s){ 
      ^
main.cpp:73:45: note: candidate function not viable: no known conversion from 'const std::__1::sub_match<const char *>' to 'const std::cmatch' (aka 'const match_results<const char *>') for 1st argument 
     std::for_each(cm.begin(), cm.end(), [](const std::cmatch &s){ 
              ^
main.cpp:73:45: note: conversion candidate of type 'void (*)(const std::cmatch &)' 
+0

Pourriez-vous pas cette question et côté fournir une spécialisation de 'default_delete' pour votre type? –

+0

Apparaît également à moins que votre type de modèle ne soit un pointeur, vous devez définir un suppresseur contenant un typedef 'pointer', où typedef correspond au type à transmettre au suppresseur. Sinon, il utilise 'T *' comme argument du suppresseur, ce qui est faux dans ce cas. Cela impliquerait qu'un lambda ne convient pas pour définir un suppresseur dans ce cas. –

Répondre

3

Construire sur devis @NulledPointer:

struct CFStringRefDeleter { 
    using pointer = CFStringRef; 
    void operator()(CFStringRef ref) { 
     CFRelease(ref); 
    } 
}; 
using CFStr_t = std::unique_ptr<CFStringRef, CFStringRefDeleter>; 
CFStr_t cfstr(CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8)); 
CFStringRef obj = cfstr.get(); 
2

Pas sûr que cela soit suffisant mais ... si je ne me trompe pas, le destructeur utilise un pointeur sur le type, pas un objet du type

Je veux dire ... vous devez définir le type comme

std::unique_ptr<CFStringRef, std::function<void(CFStringRef *)>> 
                  ^ 
          note the pointer ---------------| 

et le lambda doit recevoir (et utiliser) un pointeur

[](CFStringRef * pObj){ CFRelease(*pObj) /* ? */ }; 
+0

CFStringRef == CFString *. Deleter en cas de std :: unique_ptr appelle 'Deleter (T)' donc je ne suis pas sûr si vous avez raison – PnotNP

+1

Ceci est d'une autre manière alors. Le premier paramètre de template de unique_ptr devrait être un type et non un pointeur vers un type. Donc 'std :: unique_ptr ' –

+0

@AndreyTurkin CFString est opaque donc ne devrait pas être utilisé – PnotNP

0

Ajout de la partie "pourquoi" de la réponse de max:

Comme par unique_ptr doc

-Deleter must be FunctionObject or lvalue reference to a FunctionObject or lvalue reference to function, callable with an argument of type unique_ptr<T, Deleter>::pointer

unique_ptr<T, Deleter>::pointer est expliqué member types

unique_ptr<T, Deleter>::pointer = std::remove_reference<Deleter>::type::pointer if that type exists, otherwise T* . Must satisfy NullablePointer