1

I am trying to declare std::unique_ptr with a custom deleter:

using FILE = int;

FILE *f = nullptr;

std::unique_ptr pf(f, [](FILE *f) {});

but without a success. What is wrong?

How to use a lambda as a deleter? Do I really need decltype?

MSVC compiler error (std==C++17):

error C2641: cannot deduce template arguments for 'std::unique_ptr'
wohlstad
  • 12,661
  • 10
  • 26
  • 39
Alexey Starinsky
  • 3,699
  • 3
  • 21
  • 57
  • 2
    Quote from [cppreference](https://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr): "These two constructors are not selected by class template argument deduction." You can't use CTAD if you pass deleter, you have to provide template arguments. – Yksisarvinen Apr 26 '23 at 13:26
  • Did you include ```memory``` header in your code? You also have to explicit declare the pointee type – 0xNIC Apr 26 '23 at 13:27
  • @0xNIC yes I did – Alexey Starinsky Apr 26 '23 at 13:27
  • Related: https://stackoverflow.com/questions/70354413/automatic-template-parameter-deduction-in-unique-ptr-and-make-unique – Yksisarvinen Apr 26 '23 at 13:28

1 Answers1

3

As mentioned in the comments, you cannot use CTAD for constructing a std::unique_ptr if you pass a deleter.

If you need to use a lambda you can store it in a variable and use decltype to infer its type:

#include <memory>

//...

using FILE = int;
FILE* f = nullptr;
auto my_lambda = [](FILE* f) {};
std::unique_ptr<FILE, decltype(my_lambda)> pf(f, my_lambda);

Live demo - Godbolt


As @NebularNoise commented, c++20 supports lambdas in unevaluated contexts. If you can use c++20 (you mentioned you currently use c++17) you can make it a bit shorter:

using FILE = int;
FILE* f = nullptr;
std::unique_ptr<FILE, decltype([](FILE* f) {})> pf(f);

Live demo - Godbolt

wohlstad
  • 12,661
  • 10
  • 26
  • 39
  • 2
    C++20 makes lambdas available in unevaluated contexts, so if C++20 is an option, it could be shortened to the following: ```std::unique_ptr pf(f);``` – Nebular Noise Apr 26 '23 at 14:53