【问题标题】:C++ Forward variadic templated arguments to tupleC++ 将可变参数模板化参数转发到元组
【发布时间】:2021-06-04 16:07:23
【问题描述】:

我正在尝试创建一个基本上接受函数指针及其所有参数的函数,并将函数和这些参数存储在 std::function 和 std::tuple 中以供以后使用。我当然看到了使用可变参数的函数的典型模式,将它们完美地转发到某个地方进行存储。我在How to store variadic template arguments? 中看到了这个解决方案,它非常适合我的情况,直到我意识到它似乎只接受包装在std::ref()std::move()d 中的函数参数,我根本无法存储变量值。

在寻找另一种允许我按值和引用存储参数的解决方案时,我遇到了c++ store function and parameter list for later use,我打算重新利用它。但同时,我真的很想了解为什么第一个解决方案不允许我通过值传递任何东西:

template <typename... Ts>
class TupleCarrier {
 public:
    TupleCarrier(Ts&&... args): args_(std::make_tuple(std::forward<Ts>(args)...)) {}

    std::tuple<Ts...> args_;
};

template <typename... Ts>
void CreateCarrier(Ts&&... args) {
    TupleCarrier<Ts...> carrier(std::forward<Ts>(args)...);
}

int main() {
    int test = 4;
    CreateCarrier(std::ref(test), /*std::ref(*/test/*)*/); // fails to compile
    return 0;
}

是否像CreateCarrier 将参数作为右值引用一样简单,std::forward 要么将它们作为右值或左值引用转发,但这里根本没有办法传递常规的旧左值?我希望左值至少会被隐式视为左值引用,如果您打算按值传递,这当然可能会出现问题,但至少它会编译......

无论如何,我认为我对上述内容的微妙理解不足以自己提出正确的答案,所以这里的某种解释真的会帮助我理解一些更高级的 C++ :)

【问题讨论】:

  • 为什么不采用 0 arg 函数,让调用者将其捆绑在 lambda 中。我的意思是分开争论很可爱,但通常是浪费工作。
  • std 容器不能保存引用 &amp;。为了让 std 容器保存引用,您必须将它们包装在 std::reference_wrapper 中。
  • 我想我在下面回答你的问题非常正确和简洁......小心给我解决方案,因为我解决了它? :-P
  • 抱歉耽搁了

标签: c++ templates rvalue-reference lvalue


【解决方案1】:

问题在于定义 std::make_tuple() 的方式:它 std::decays 它的参数类型。

检查https://en.cppreference.com/w/cpp/utility/tuple/make_tuple“可能的实施”部分以查看详细信息。

所以,_args 成员最终变成:

std::tuple<std::reference_wrapper<int>,int &>

因为那里没有添加衰变。 但是 make_tuple() 的结果是 std::tuple - int 的标识在此过程中丢失 - 您将引用初始化器的 value 参数 - 这将是一个悬挂引用。因此,您的第一个元组位置中的 int& 不能通过按值传递的 int 参数初始化。

无论如何,解决方案也是以这种方式衰减 args_ 声明:

std::tuple< std::decay_t< Ts > ...> args_;

然后事情编译得很好,因为您已经将接收器 (args_) 与内部衰减其参数的 make_tuple() 的结果相匹配。

那么 args_ 的类型最终是:

std::tuple<std::reference_wrapper<int>,int>

一切都是共存的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    相关资源
    最近更新 更多