其他分享
首页 > 其他分享> > c – 完美转发函数以构建函数列表类

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...> or std::tuple<F&&...>

我认为在你的情况下它应该是std :: tuple< F ...>,因为你想存储左值引用或值.

的std ::元组&LT F&安培;&安培; …&GT将存储左值引用或右值引用 – 这将导致临时引用的悬空引用.

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, or F&&...

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