我有这样的功能
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&&...>
theArgs
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");
}
关于c++ - 将一组转发引用包装在一个元组中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42263987/