Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 构造函数中的通用引用导致失败,can';t将可调用函子赋给std::function_C++_Templates_C++11_Universal Reference - Fatal编程技术网

C++ 构造函数中的通用引用导致失败,can';t将可调用函子赋给std::function

C++ 构造函数中的通用引用导致失败,can';t将可调用函子赋给std::function,c++,templates,c++11,universal-reference,C++,Templates,C++11,Universal Reference,在下面的完整测试用例中,如果我使用第一个按值获取函子并将其移动到位的向量,那么代码将按照预期编译和工作 但是,如果我使用通用引用ctor,它将无法编译(我在下面包含了叮当声错误消息) 我如何解决这个问题,或者我做错了什么 #include <functional> #include <utility> #include <exception> template<typename F> struct py_catch { F func;

在下面的完整测试用例中,如果我使用第一个按值获取函子并将其移动到位的向量,那么代码将按照预期编译和工作

但是,如果我使用通用引用ctor,它将无法编译(我在下面包含了叮当声错误消息)

我如何解决这个问题,或者我做错了什么

#include <functional>
#include <utility>
#include <exception>

template<typename F>
struct py_catch {
    F func;
    /*  
    //Works
    py_catch(F f) 
    :   func ( std::move(f) )
    {   } */
    //Doesn't
    template<typename F2> 
    py_catch(F2&& f)  
    :   func ( std::forward<F2>(f) )
    {   }   

    py_catch(py_catch&&)=default;
    py_catch(const py_catch&)=default;
    py_catch& operator=(const py_catch&)=default;
    py_catch& operator=(py_catch&&)=default;

    template<typename... Args>
    auto operator()(Args&&... args)
    -> decltype(func(std::forward<Args>(args)...)) {
        try {
            return func(std::forward<Args>(args)...);
        }
        catch(const std::exception&) {
                    throw;
        }
    }   
};

template<typename F>
py_catch<typename std::remove_reference<F>::type> make_py_catch(F&& f) {
    return py_catch<typename std::remove_reference<F>::type>(std::forward<F>(f));
}

int main() {
    std::function<void()> s;
    s = make_py_catch([]{});
}
#包括
#包括
#包括
模板
结构py_catch{
F func;
/*  
//工作
py_捕捉(F)
:func(标准::移动(f))
{   } */
//没有
模板
py_捕捉(F2和f)
:func(标准::前进(f))
{   }   
py_catch(py_catch&&)=默认值;
py_catch(const py_catch&)=默认值;
py_catch&运算符=(const py_catch&)=默认值;
py_catch&operator=(py_catch&&)=默认值;
模板
自动运算符()(Args&&…Args)
->decltype(func(std::forward(args)…){
试一试{
返回函数(std::forward(args)…);
}
捕获(const std::exception&){
投掷;
}
}   
};
模板
py_catch make_py_catch(F&F){
返回py_捕捉(标准::前进(f));
}
int main(){
std::函数s;
s=使捕获([]{});
}
编译错误:

testcase2.cpp:16:7: error: no matching constructor for initialization of '<lambda at testcase2.cpp:43:23>'
        :   func ( std::forward<F2>(f) )
            ^      ~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/functional:1764:10: note: in instantiation of function template specialization 'py_catch<<lambda at testcase2.cpp:43:23> >::py_catch<py_catch<<lambda at testcase2.cpp:43:23> > &>' requested here
            new _Functor(*__source._M_access<_Functor*>());
                ^
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/functional:1799:8: note: in instantiation of member function 'std::_Function_base::_Base_manager<py_catch<<lambda at testcase2.cpp:43:23> > >::_M_clone' requested here
              _M_clone(__dest, __source, _Local_storage());
              ^
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/functional:2298:33: note: in instantiation of member function 'std::_Function_base::_Base_manager<py_catch<<lambda at testcase2.cpp:43:23> > >::_M_manager' requested here
            _M_manager = &_My_handler::_M_manager;
                                       ^
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/functional:2173:4: note: in instantiation of function template specialization 'std::function<void ()>::function<py_catch<<lambda at testcase2.cpp:43:23> > >' requested here
          function(std::forward<_Functor>(__f)).swap(*this);
          ^
testcase2.cpp:43:7: note: in instantiation of function template specialization 'std::function<void ()>::operator=<py_catch<<lambda at testcase2.cpp:43:23> > >' requested here
    s = make_py_catch([]{});
      ^
testcase2.cpp:43:23: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'py_catch<<lambda at testcase2.cpp:43:23> >' to 'const <lambda at testcase2.cpp:43:23>' for 1st argument
    s = make_py_catch([]{});
                      ^
testcase2.cpp:43:23: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'py_catch<<lambda at testcase2.cpp:43:23> >' to '<lambda at testcase2.cpp:43:23>' for 1st argument
    s = make_py_catch([]{});
                      ^
testcase2.cpp:43:23: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided
1 error generated.
testcase2.cpp:16:7:错误:没有用于“”初始化的匹配构造函数
:func(标准::前进(f))
^      ~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../../../../include/c++/4.7.2/functional:1764:10:注意:在函数模板专门化的实例化中,此处请求“py_catch::py_catch”
新的_函子(*__source._M_access());
^
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../../../../../include/c++/4.7.2/functional:1799:8:注意:在成员函数的实例化中,此处请求“std::_function_base::_base_manager::_M_clone”
_M_clone(u dest,u source,_Local_storage());
^
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../../../../../include/c++/4.7.2/functional:2298:33:注意:在成员函数的实例化中,此处请求“std::_function_base::_base_manager::_M_manager”
_M_经理=&_我的处理程序::_M_经理;
^
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../../../../../include/c++/4.7.2/functional:2173:4:注意:在函数模板专门化的实例化中,此处请求“std::function::function”
函数(std::forward(_f)).swap(*this);
^
testcase2.cpp:43:7:注意:在函数模板专门化的实例化中,此处请求了“std::function::operator=”
s=使捕获([]{});
^
testcase2.cpp:43:23:注意:候选构造函数(隐式副本构造函数)不可行:没有已知的第一个参数从“py_catch”到“const”的转换
s=使捕获([]{});
^
testcase2.cpp:43:23:注意:候选构造函数(隐式移动构造函数)不可行:没有已知的第一个参数从“py_catch”到“”的转换
s=使捕获([]{});
^
testcase2.cpp:43:23:注意:候选构造函数(隐式默认构造函数)不可行:需要0个参数,但提供了1个
生成1个错误。

我认为问题在于转换构造函数模板
模板py_catch(F2&&)
太贪婪了。触发错误的另一种方法是:

int main() {
    auto x( make_py_catch([]{}) );
    auto y(x);
}
此复制构造使用某种类型的左值
py\u catch
。复制构造函数需要一个
py\u catch常量&
,而贪婪模板提供了一个重载,其类型为
py\u catch&
。[over.ics.rank]/3中的一条特殊规则现在表示,优先使用引用不太合格类型的重载。因此,调用的不是复制构造函数,而是构造函数模板,它尝试使用整个
py_catch
对象(而不是其
func
成员)初始化数据成员(lambda)

一个简单但可能不是最优的解决方案是为非常量左值
py_-catch(py_-catch&)=default提供另一个拷贝向量。但是,当您使用继承或用户定义转换时,构造函数模板仍然是首选


另一个解决方案是在构造函数模板上使用一些SFINAE;例如,检查
是否相同
是否基本
或类似的内容(请记住
删除
F2
中可能的引用)<代码>是可转换的
也可以工作,但我怀疑它会递归地尝试使用构造函数模板进行检查。

我认为问题在于转换构造函数模板
模板py_catch(F2&&)
太贪婪了。触发错误的另一种方法是:

int main() {
    auto x( make_py_catch([]{}) );
    auto y(x);
}
此复制构造使用某种类型的左值
py\u catch
。复制构造函数需要一个
py\u catch常量&
,而贪婪模板提供了一个重载,其类型为
py\u catch&
。[over.ics.rank]/3中的一条特殊规则现在表示,优先使用引用不太合格类型的重载。因此,调用的不是复制构造函数,而是构造函数模板,它尝试使用整个
py_catch
对象(而不是其
func
成员)初始化数据成员(lambda)

一个简单但可能不是最优的解决方案是为非常量左值
py_-catch(py_-catch&)=default提供另一个拷贝向量。但是,当您使用继承或用户定义转换时,构造函数模板仍然是首选

另一个解决方案是在构造函数模板上使用一些SFINAE;例如,检查
是否相同
是否基本
或类似的内容(请记住
删除
F2
中可能的引用)<代码>是可转换的
也可以工作,但我怀疑它可能会递归地尝试使用构造函数模板来执行I