c++ - 将一组转发引用包装在一个元组中

标签 c++ tuples c++14 perfect-forwarding forwarding-reference

我有这样的功能

template <typename... Args> void foo(Args&&... args);

我需要在末尾添加一个带有默认参数的额外参数。由于包需要放在最后,我正在考虑将功能更改为

template <typename... Args> void foo(std::tuple<Args&&...> args,
                                     const std::string& name = {});

问题是,在 tuple 中传递参数的最佳方式是什么? . 我的理解是在std::tuple<Args&&...> Args不再转发引用,而是严格右值引用。如何获取 args 的转发引用行为包裹在 tuple 中,例如接受 std::forward_as_tuple并保留各个元组元素的引用类型。另外,在这里传递元组的最佳方式是什么,

std::tuple<Args&&...> args

const std::tuple<Args&&...>& args

std::tuple<Args&&...>&& args

?

我需要使用 std::forward 吗?在函数内的元组元素上,或简单地 std::get他们?

最佳答案

My understanding is that in the std::tuple<Args&&...> the Args are not forwarding references anymore

正确。

but strictly rvalue references

是的,除非Args明确指定,在这种情况下 reference collapsing可以将它们变成左值引用,即 foo<int&>(...)将导致 Args&& -> int& && -> int& .

what is the best way to pass the arguments in a tuple.

这取决于 foo 的预期用途.如果你不需要知道什么Args...确实如此,您可能可以逃脱:

template <typename Tuple>
void foo(Tuple&& args, const std::string& name = {});

在这种情况下,仍然可以使用 std::tuple_element_t<N, std::decay_t<Tuple>> 访问个别类型.

如果你确实想知道Args...里面foo (没有任何额外的抽象级别),您可能想要推断出确切的类型,而不需要任何引用:

template <typename.... Args>
void foo(std::tuple<Args...>&& args, const std::string& name = {});

请注意,如果有人使用 std::forward_as_tuple内部有左值和右值,值类别将存储在 Args 中你仍然可以使用 std::forward 转发这些参数(std::forward 仅限于转发引用,将其视为条件转换)。

Also, what's the best way to pass the tuple here

可能 Tuple&&如前所述。如果没有,那么这又取决于用法。如果你使用 const std::tuple<Args...>& ,然后查看 std::get 的重载列表,您会看到值类别和常量传播到 std::get 的返回值(模 reference collapsing )。 std::tuple<Args...>&& 也是如此.此外,使用后者,您将必须使用元组右值作为参数( foo(std::forward_as_tuple(...), ...) 而不是 foo(my_tuple, ...) )。

另一种解决方案是接受参数包,并检测最后一个参数是否可以被const std::string& 绑定(bind)。与否:

#include <string>
#include <utility>
#include <tuple>
#include <type_traits>

struct dummy {};

template <typename... Args>
void foo_impl(Args&&... args)
{
    const std::string& s = std::get<sizeof...(Args) - 1>(std::forward_as_tuple(std::forward<Args>(args)...));
}

template <typename... Args>
auto foo(Args&&... args)
    -> std::enable_if_t<std::is_constructible<std::string, std::tuple_element_t<sizeof...(Args), std::tuple<dummy, Args...>>>{}>
{
    foo_impl(std::forward<Args>(args)...);
}

template <typename... Args>
auto foo(Args&&... args)
    -> std::enable_if_t<!std::is_constructible<std::string, std::tuple_element_t<sizeof...(Args), std::tuple<dummy, Args...>>>{}>
{
    foo_impl(std::forward<Args>(args)..., "default");
}

DEMO

关于c++ - 将一组转发引用包装在一个元组中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42263987/

相关文章:

python - 将一对列表/元组解压缩成两个列表/元组

swift - 我可以将元组与 AnyObject 一起使用吗?

c++ - 有没有我可以直接获取地址的右值?

c++ - 我的程序需要读取一个文本文件,文本文件中的数据需要用逗号分隔(C++)

c++ - 无法在 ubuntu 上的 netbeans 中进入 C++ 程序像素城市

c++ - 数组向后排序?

java - 在Java中应用MapReduce

C++ unicode UTF-16编码

c++ - 读一个大文件统计单词重复K次的次数

c++ - 简化将不同类型分派(dispatch)给 C++ 中不同函数的代码