接受一组对象类型的所有组合可能性作为在 C++ 中运行的参数
Accept all combinatorial possibilities for a set of object types as parameter to function in C++
给定三个不同的空 structs
、A
、B
和 C
,我想要一个函数 foo
接受任意数字的任意组合这三个参数,例如:
struct A {};
struct B {};
struct C {};
// Foo has a required parameter that must be the first one given. Anything else is optional.
foo(1);
foo(1, A{});
foo(1, B{});
foo(1, B{}, A{});
foo(1, A{}, C{}, B{});
我认为可变参数模板和函数重载在这种情况下会有所帮助,所以这是我尝试过的方法:
struct A {};
struct B {};
struct C {};
template <typename... ExtraParams>
void foo(int x, ExtraParams&&...)
{
std::cout << "x = " << x;
}
template <typename... ExtraParams>
void foo(int x, A&&, ExtraParams&&... extra)
{
foo(x, extra...);
std::cout << " with A";
}
template <typename... ExtraParams>
void foo(int x, B&&, ExtraParams&&... extra)
{
foo(x, extra...);
std::cout << " with B";
}
// same for C
但是,调用 f(2, A{}, B{})
时,只会打印 x = 2 with A
。我想我不明白为什么这不起作用,但我不太确定我应该如何处理这种情况。
EDIT 我正在测试的代码针对已知类型使用了右值引用,例如:
template <typename... ExtraParams>
void foo(int x, A&&, ExtraParams&&... extra)
{
foo(x, extra...);
std::cout << " with A";
}
这将产生我提到的确切行为(虽然我不知道为什么)。
问题是当您将参数 extra
作为 foo(x, extra...);
传递给 foo
的其他重载时,它们是 lvalues 并且不能绑定到右值引用,如 A&&
和 B&&
.
(强调我的)
The following expressions are lvalue expressions:
- the name of a variable, a function
, a template parameter object (since C++20)
, or a data member, regardless of type, such as
std::cin or std::endl. Even if the variable's type is rvalue
reference, the expression consisting of its name is an lvalue
expression;
你应该使用 std::forward
to forward the parameters (as rvalues if the original arguments passed are rvalues, i.e. to take advantage of forwarding reference)。例如
foo(x, std::forward<ExtraParams>(extra)...);
给定三个不同的空 structs
、A
、B
和 C
,我想要一个函数 foo
接受任意数字的任意组合这三个参数,例如:
struct A {};
struct B {};
struct C {};
// Foo has a required parameter that must be the first one given. Anything else is optional.
foo(1);
foo(1, A{});
foo(1, B{});
foo(1, B{}, A{});
foo(1, A{}, C{}, B{});
我认为可变参数模板和函数重载在这种情况下会有所帮助,所以这是我尝试过的方法:
struct A {};
struct B {};
struct C {};
template <typename... ExtraParams>
void foo(int x, ExtraParams&&...)
{
std::cout << "x = " << x;
}
template <typename... ExtraParams>
void foo(int x, A&&, ExtraParams&&... extra)
{
foo(x, extra...);
std::cout << " with A";
}
template <typename... ExtraParams>
void foo(int x, B&&, ExtraParams&&... extra)
{
foo(x, extra...);
std::cout << " with B";
}
// same for C
但是,调用 f(2, A{}, B{})
时,只会打印 x = 2 with A
。我想我不明白为什么这不起作用,但我不太确定我应该如何处理这种情况。
EDIT 我正在测试的代码针对已知类型使用了右值引用,例如:
template <typename... ExtraParams>
void foo(int x, A&&, ExtraParams&&... extra)
{
foo(x, extra...);
std::cout << " with A";
}
这将产生我提到的确切行为(虽然我不知道为什么)。
问题是当您将参数 extra
作为 foo(x, extra...);
传递给 foo
的其他重载时,它们是 lvalues 并且不能绑定到右值引用,如 A&&
和 B&&
.
(强调我的)
The following expressions are lvalue expressions:
- the name of a variable, a function
, a template parameter object (since C++20)
, or a data member, regardless of type, such as std::cin or std::endl. Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression;
你应该使用 std::forward
to forward the parameters (as rvalues if the original arguments passed are rvalues, i.e. to take advantage of forwarding reference)。例如
foo(x, std::forward<ExtraParams>(extra)...);