Inconsistencies with C++11 function signatures

82 Views Asked by At

I have questions regarding functions, more specific on function signatures and how to pass them. I might be a trivial or even stupid question, but I couldn't find a satisfying answer yet.

Please consider this example which uses a std::unique_ptr to manage a file pointer:

#include <iostream>
#include <memory>

void func1(FILE* f)
{
    std::cout << "func1 called" << std::endl;
    fclose(f);
}

int main() 
{
    FILE* f = fopen("testfile.txt", "w");
    if(f)
    {
        std::unique_ptr<FILE, void(*)(FILE*)> fptr(f, &func1);
    }

    return 0;
}

This kind of smart pointer needs a functions signature as second template argument (shared_ptr does not for some odd reason). My current understanding of interpreting the signature here is

void () (FILE) is a pointer to a function returning nothing (void) and a filepointer as argument.

As a result, the user has to pass the address of the desired function with the address operator. At this point, a few questions arise:

1.) Removal of the address operator works just as well, no compiler warning is thrown, code works. Shouldn't this be an error/warning?

2.) If I use a reference to a function (e.g. unique_ptr<FILE, void(&)(FILE*)>(f, func1) ) it works as expected, so is this a superior way to pass a function as it is unambiguous?

3.) Removing the middle specifier altogether (e.g. unique_ptr<FILE, void()(FILE*)>(f, func1) ) causes compiler errors, so is passing a function by value impossible in general? (if it is, then it would make sense to overload the version in 1. by implicitly converting the function to a function pointer)

1

There are 1 best solutions below

0
Ivan Vorobyev On BEST ANSWER

Function name is the always address of function (pointer to the function). If you want to use something else you can use some wrapper, e.g. std::function:

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

class Closer {
public:
    void operator ()(FILE *f) {
        std::cout << "func1 called" << std::endl;
        fclose(f);
    }
};

int main() 
{
    FILE* f = fopen("testfile.txt", "w");
    if(f)
    {
        std::unique_ptr<FILE, std::function<void(FILE*)>> fptr(f, Closer());
    }

    return 0;
}

Lambda in that case is anonymous functional object.