简体   繁体   English

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

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

I've recently learned that C++ can perform implicit function-to-function-pointer cast whenever it found necessary.我最近了解到 C++ 可以在必要时执行隐式函数到函数指针转换 For example, in my example below, my_func_1 and my_func_2 are equivalent.例如,在下面的示例中, my_func_1my_func_2是等价的。 However, vector_1 and vector_2 are not, and in fact, vector_2 will give a compile error.但是vector_1vector_2不是,实际上vector_2会报编译错误。 Similar compile errors also happen for other standard containers, eg unordered_map .其他标准容器也会发生类似的编译错误,例如unordered_map Why is it so?为什么会这样?

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
}

Here is the compile error message (shortened to highlight the error):这是编译错误消息(缩短以突出显示错误):

/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-g /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ext/new_allocator.h:96:7:错误: 'address' 的多个重载实例化为相同的签名 '__gnu_cxx::new_allocator<my_class ()>::const_pointer (__gnu_cxx::new_allocator<my_class ()>::const_reference) const noexcept' (又名 'my_class (*(my_class ( &)()) const noexcept)()') 地址(const_reference __x) const _GLIBCXX_NOEXCEPT ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../。 ./include/c++/9/bits/allocator.h:112:30: 注意:在模板 class '__gnu_cxx::new_allocator<my_class ()>' 的实例化中 class< allocator: public __gnu_cxx::new_allocator<my_class ()>' bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ext/alloc_traits.h:49:47:注意:在实例化模板 class 'std::allocator<my_class ()>' 在这里请求模板<typename _Alloc, typename = typename _Alloc::value_type> ^ /usr/bin/../lib/gcc/x86_64-linux-g nu/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; nu/9/../../../../include/c++/9/bits/stl_vector.h:83:35: 注意:在 '__alloc_traits<std::allocator<my_class ( )>>' 这里需要 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:注意:在模板 class 'std::_Vector_base 的实例化中<my_class (), std::allocator<my_class ()>>' 在此处请求 class 向量:受保护 _Vector_base<_Tp, _Alloc> ^ 第 7 行:字符 24:注意:在模板 class 'std::vector<my ), std::allocator<my_class ()>>' 在这里请求 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 ^ // 给出编译错误 ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ext/new_allocator.h: 92:7:注意:之前的声明在这里地址(参考 __x)const _GLIBCXX_NOEXCEPT ^

In this declaration:在此声明中:

vector<my_class()> vector_2; 

the type used to instantiate the vector is myclass() , which is a function type.用于实例化向量的类型是myclass() ,它是 function 类型。 Specifically it's a function that takes no arguments, and returns a my_class .具体来说,它是一个 function ,它不接受 arguments,并返回一个my_class

A function type is not copy-assignable , as can be seen from this test:一个 function 类型是不可复制分配的,从这个测试可以看出:

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

Being copy-assignable is one of the requirements on the type used as a template parameter for std::vector , and so this declaration doesn't compile.可复制分配是对用作std::vector模板参数的类型的要求之一,因此此声明无法编译。


The remaining declarations are fine:其余的声明很好:

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

Due to implicit conversion to function-pointers of types used in function parameters, the following declarations are equivalent:由于隐式转换为 function 参数中使用的类型的函数指针,以下声明是等效的:

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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 函数到函数指针“衰减” - Function-to-function-pointer "decay" 使用enable_if和SFINAE时函数参数类型推导(std容器,例如vector)失败 - function argument type deduction (std container e.g. vector) fails when using enable_if and SFINAE 为什么成员函数需要'&'(例如在std :: bind中)? - Why does a member function needs '&' (e.g. in std::bind)? 比较函数放在哪里(例如std :: sort)? - Where to put comparison function for use with (e.g.) std::sort? 一系列相关函数的通用函数(例如std :: stoi,std :: stof,std :: stod等) - Generic function for a family of related functions (e.g. std::stoi, std::stof, std::stod etc) std :: function隐式类型转换 - std::function implicit type conversion 隐式转换为std :: vector - Implicit conversion to std::vector 没有匹配的 function 来调用:错误:必须使用 '.*' 或 '-&gt;*' 来调用指向成员 function 在 'f (...)' 中的指针,例如 '(... -&gt;* f) (...)' - No matching function to call: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘f (…)’, e.g. ‘(… ->* f) (…)’ 定义分段函数(例如多项式) - Defining a piecewise function (e.g. polynomial) 从函数返回const char *的正确方法,例如,重写std :: exception :: what() - Proper method of returning const char* from a function, e.g., overriding std::exception::what()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM