[SOLVED] Inconsistencies with C++11 function signatures

Issue

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)

Solution

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.

Answered By – Ivan Vorobyev

Answer Checked By – Candace Johnson (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.