c++ - 功能完美转发构建功能列表类

标签 c++ function c++11 template-meta-programming perfect-forwarding

考虑以下构建类存储函数的代码。

// 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 背后发生的所有类型推导。和通用引用。在上面的代码中,我有三个问题:

  • 应该_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正在做这项工作。

编辑: 这种情况安全吗,当operator()function_list (此处未显示)不保证在同一语句中被调用?

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基本保留了x的类型分类通过查看如何 T被推导出来。


Should _f be of type std::tuple<F...> or std::tuple<F&&...>

我认为你的情况应该是 std::tuple<F...> ,因为您要存储左值引用

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

function_list应该采取 F...出于本答案开头列出的原因作为模板参数(即避免对临时对象的悬空引用)

它仍然需要 std::forward<F>(f)...作为允许右值被转发的参数(即将右值移动到function_list的元组中)

关于c++ - 功能完美转发构建功能列表类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42032755/

相关文章:

c++11 - unique_ptr 向量的取消引用包装器?

c++ - 相同的代码,如果优先级队列中存在平局,则顺序不同,使用 clang 和 gcc

c++ - 我应该什么时候使用 Boost 的 lexical_cast?它是不得已的机制吗?

c++ - c++中抛出的对象在哪里?

c - 用指针 C 循环

c++ - 无法在 std::thread 中传递一维数组

c++ - 将 double 类型转换为 unsigned long long 类型导致来自 Windows 和 Linux 的 C++

c++ - 错误 : deque iterator not dereferenceable

c - 当我传入函数指针时出现错误

javascript - 从作为参数传递给 JavaScript 中另一个函数的函数中提取参数