c – 完美转发函数以构建函数列表类
作者:互联网
请考虑以下构建类存储函数的代码.
// Function list class
template <class... F>
struct function_list
{
template <class... G>
constexpr function_list(G&&... g) noexcept
: _f{std::forward<G>(g)...}
{
}
std::tuple</* F... OR F&&... */> _f;
};
// Function list maker
template <class... F, class R = /* Can we compute the return type here? */>
constexpr R make_function_list(F&&... f)
{
return function_list<
/* decltype(std::forward<F>(f))...
* OR F...
* OR F&&...
*/>(std::forward<F>(f)...);
}
我希望这些函数能够完美地转发(无论它们是函数指针,函子,lambdas ……).但我并不完全理解std :: forward和universal reference背后发生的所有类型推论.在上面的代码中,我有三个问题:
> _f应该是std :: tuple< F ...>类型或者std :: tuple< F&& ...> (为什么?)
>是否可以在模板参数列表中推导出返回类型R(因为手动而不是auto / decltype(auto)有助于理解发生了什么)
>在制造商中,function_list模板参数应该是什么:decltype(std :: forward< F>(f)…),F或F&& …(以及为什么?)
注意:function_list的构造函数不是要直接调用,而是make_function_list正在完成这项工作.
编辑:
这种情况是否安全,当function_list的operator()(此处未显示)不能保证在同一语句中被调用时?
template <class... F>
constexpr function_list<F...> make_function_list(F&&... f)
{
return function_list<F&&...>(std::forward<F>(f)...);
}
解决方法:
But I don’t exactly understand all the type deduction happening behind
std::forward
and universal references.
通过一个例子来理解它非常简单.
template <typename T>
void f(T&&)
{
std::tuple<T>{}; // (0)
std::tuple<T&&>{}; // (1)
}
在(0)的情况下:
>对于右值,T被推导为T.
> T被推断为T&对于左值.
在(1)的情况下:
> T被推断为T&&对于右值
> T被推断为T&对于左值.
如您所见,两者之间的唯一区别是如何推导出右值.
关于std :: forward,这就是它的作用:
template <typename T>
void g(T&&);
template <typename T>
void f(T&& x)
{
g(x) // (0)
g(std::forward<T>(x)); // (1)
}
在(0)的情况下:
> x始终是左值.
在(1)的情况下:
> x被投射到T&&如果T被推断为T.
> x否则保持左值.
std :: forward基本上通过查看如何推导出T来保留x的类型类别.
Should _f be of type
std::tuple<F...>
orstd::tuple<F&&...>
我认为在你的情况下它应该是std :: tuple< F ...>,因为你想存储左值引用或值.
的std ::元组< F&安培;&安培; …>将存储左值引用或右值引用 – 这将导致临时引用的悬空引用.
Is it possible to deduce the return type
R
in the template parameter list
是的,它只是function_list< F ...>.
template <class... F, class R = function_list<F...>>
constexpr R make_function_list(F&&... f)
{
return function_list<F...>(std::forward<F>(f)...);
}
您甚至不需要R模板参数.
template <class... F>
constexpr function_list<F...> make_function_list(F&&... f)
{
return function_list<F...>(std::forward<F>(f)...);
}
In the maker, what the
function_list
template argument should be:decltype(std::forward<F>(f)...)
,F
, orF&&...
function_list应该将F …作为模板参数,因为这个答案开头列出的原因(即避免悬挂对临时工具的引用).
它仍然应该使用std :: forward< F>(f)…作为其参数,以允许rvalues被转发(即将rvalues移动到function_list的元组中).
标签:perfect-forwarding,c,c11,function,template-meta-programming 来源: https://codeday.me/bug/20190828/1753884.html