隐式函数到函数指针的转换不适用于标准容器(例如向量)

Implicit function-to-function-pointer conversion not working for std containers (e.g. vector)

我最近了解到 C++ 可以在必要时执行 。例如,在我下面的示例中,my_func_1my_func_2 是等价的。但是,vector_1vector_2不是,实际上vector_2会给出编译错误。其他标准容器也会发生类似的编译错误,例如unordered_map。为什么会这样?

class my_class {
    // dummy class
};

int main() {
    vector<my_class(*)()> vector_1; // correct one
    vector<my_class()> vector_2;    // gives compile error
    
    // However, both of the below are OK due to implicit
    // function-to-function-pointer conversion
    void my_func_1(my_class(*)());
    void my_func_2(my_class());    // equivalent to the one above
}

这是编译错误消息(为了突出错误而缩短):

/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ext/new_allocator.h:96:7: error: multiple overloads of 'address' instantiate to the same signature '__gnu_cxx::new_allocator<my_class ()>::const_pointer (__gnu_cxx::new_allocator<my_class ()>::const_reference) const noexcept' (aka 'my_class (*(my_class (&)()) const noexcept)()') address(const_reference __x) const _GLIBCXX_NOEXCEPT ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/allocator.h:112:30: note: in instantiation of template class '__gnu_cxx::new_allocator<my_class ()>' requested here class allocator : public __allocator_base<_Tp> ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ext/alloc_traits.h:49:47: note: in instantiation of template class 'std::allocator<my_class ()>' requested here template<typename _Alloc, typename = typename _Alloc::value_type> ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:83:35: note: in instantiation of default argument for '__alloc_traits<std::allocator<my_class ()>>' required here typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template ^~~~~~~~~~~~~~~~~~~~~~ /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:386:30: note: in instantiation of template class 'std::_Vector_base<my_class (), std::allocator<my_class ()>>' requested here class vector : protected _Vector_base<_Tp, _Alloc> ^ Line 7: Char 24: note: in instantiation of template class 'std::vector<my_class (), std::allocator<my_class ()>>' requested here vector<my_class()> vector_2; // gives compile error ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ext/new_allocator.h:92:7: note: previous declaration is here address(reference __x) const _GLIBCXX_NOEXCEPT ^

在此声明中:

vector<my_class()> vector_2; 

用来实例化vector的类型是myclass(),是函数类型。具体来说,它是一个不带参数的函数,并且 returns a my_class.

一个函数类型不是copy-assignable,从这个测试可以看出:

static_assert(not std::is_copy_assignable_v<Foo()>);

copy-assignable 是对用作 std::vector 模板参数的类型的要求之一,因此此声明无法编译。


剩下的声明没问题:

vector<my_class(*)()> vector_1; // vector of function pointer type

由于隐式转换为函数参数中使用的类型的函数指针,以下声明是等效的:

void my_func_1(my_class(*)());  // function taking a function pointer 
                                // to a function that takes no arguments
                                // and returns a my_class

void my_func_2(my_class());     // function taking a function that takes no 
                                // arguments and returns a my_class