0

I want to open a file and perform some operation on the file, the testOpen and testClose are wrappers around the API function test_open and test_close so that if there's an error in performing these operations I can throw a exception which would help in tracking down the error.

To achieve this I'm using a std::unique_ptr with a custom deleter that performs the close operation on the file. Now since I'm not using the API function directly instead a wrapper around the API call, I want to pass the function parameter std::string const& path as an argument to the wrapper testClose(test*, std::string&)

But I'm not able to pass the std::string const& path to the lambda function of the custom deleter parameter of unique_ptr.

test is a C library.

This is what I tried.

using test_ptr = std::unique_ptr<test, void(*)(test*)>;

test_ptr testOpen(std::string const& path) {
    test_ptr tester(test_open(...), [path](test* t){
        testClose(t, path); // a wrapper around the test_close API function which closes the file at path and might throw an exception if the close operation fails.
    });

    if(!tester) {
        throwTestError(path); // throws an exception
    }

    return test;
}

But throws an error: no matching function for call to 'std::unique_ptr<test, void(\*)(test*)>::unique_ptr(test*, testOpen(std::string const&)::<lambda(test*)>)'

Also this seems to work fine.

using test_ptr = std::unique_ptr<test, void(*)(test*)>;

test_ptr testOpen(std::string const& path) {
    test_ptr tester(test_open(...), [](test* t){
        test_close(t);
    });

    if(!tester) {
        throwTestError(path); // throws an exception
    }

    return test;
}

When I don't use the Wrapper testClose() instead making the API call directly.

Is there a possible way such that I could use my wrapper testClose() instead of making the API call?

user3840170
  • 26,597
  • 4
  • 30
  • 62

1 Answers1

0

A lambda with captures can never be used as a function pointer. Only capture-less lambdas can be used for function pointers.

If you have a recent compiler and can build with the C++20 standard, you can use a template type-alias for the test_ptr type, and auto return type deduction for the function:

template<typename F>
using test_ptr = std::unique_ptr<test, F>;

auto testOpen(std::string const& path) {
    test_ptr tester(test_open(), [path](test* t){
        testClose(t, path); // a wrapper around the test_close API function which closes the file at path and might throw an exception if the close operation fails.
    });

    if(!tester) {
        throwTestError(path); // throws an exception
    }

    return tester;
}

While this will build, you need to use auto and type-deduction everywhere you use the pointer. The type-alias template test_ptr is not possible to use for the object returned by testOpen. This is a major limiting factor that might prevent its use for your use-case.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621