与 C++11 函数签名不一致

Inconsistencies with C++11 function signatures

我对函数有疑问,更具体的是函数签名以及如何传递它们。我可能是一个微不足道甚至愚蠢的问题,但我还没有找到满意的答案。

请考虑这个使用 std::unique_ptr 来管理文件指针的示例:

#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;
}

这种智能指针需要函数签名作为第二个模板参数(shared_ptr 由于某些奇怪的原因不需要)。我目前对这里解释签名的理解是

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

因此,用户必须使用地址运算符传递所需函数的地址。此时,出现几个问题:

1.) 删除地址运算符同样有效,没有抛出编译器警告,代码有效。这不应该是 error/warning 吗?

2.) 如果我使用对函数的引用(例如 unique_ptr<FILE, void(&)(FILE*)>(f, func1) ),它会按预期工作,那么这是传递函数的更好方法吗?

3.) 完全删除中间说明符(例如 unique_ptr<FILE, void()(FILE*)>(f, func1) )会导致编译器错误,因此通常不可能按值传递函数吗? (如果是,那么通过将函数隐式转换为函数指针来重载 1. 中的版本是有意义的)

函数名是函数的始终地址(指向函数的指针)。如果您想使用其他东西,您可以使用一些包装器,例如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 是匿名函数对象。