问题描述
基本上可以用以下示例来总结问题:
Basically the problem can be summed up with this example:
template <typename ...Us>
void foo(Us...) { std::cout << "A\n"; }
template <typename ...Us>
void foo(Us..., int) { std::cout << "B\n"; }
int main(){
foo(1,2,3);
}
这称为第一个 foo
(打印 A
)。我该如何调用第二个 foo
?
This calls the first foo
(prints A
). How can I get it to call the second foo
?
如果该模板使用的是非可变模板,或者 int是第一个参数,然后重载规则将调用正确的函数。也就是说,特定类型( int
)比模板更好地匹配,因此它将调用第二个 foo
。但是显然可变参数模板不是这种情况吗?当不是最后一个参数时,是否可以重载可变参数模板?
If this used a non-variadic template, or if the "int" was the first argument, then the overload rules would call the right function. That is, a specific type (int
) is a better match than a template so it would call the second foo
. But apparently that's not the case with variadic templates? Is there any way to overload a variadic template when it's not the last argument?
推荐答案
何时参数包不会出现在参数声明的最后,它是一个非推论上下文。非推断上下文意味着必须显式给出模板参数。这就是为什么 foo
#1是更好的重载的原因。您可以通过提供显式参数( foo< int,int>(1,2,3)
)强制第二次重载调用,或者如您所说,移动 int
放在最前面。
When a parameter pack doesn't appear last in the parameter declaration, it is a non-deduced context. A non-deduced context means that the template arguments have to be given explicitly. This is why foo
#1 is a better overload. You can force the second overload call by providing explicit arguments (foo<int,int>(1,2,3)
) or as you said, move the int
to the front.
为了清楚起见,您可以 用可变参数模板重载函数,但是当它们不作为最后一个参数出现时,就无法推导它们,当不提供显式参数时,它们自动取消其作为候选的资格。提供模板参数后,模板参数将替换为其提供的类型,并且生成的 non-template 函数可用于重载解决方案。
To make things clear, you can overload a function with variadic templates, but when they do not appear as the last argument, they cannot be deduced, which automatically disqualifies them as candidates when explicit arguments are not provided. When they are provided, the template parameters are replaced with their provided types and the resulting non-template function is a candidate in overload resolution.
要回答您的问题,您可以将所有参数放入一个元组,然后挑选出最后一个参数并对其进行测试。然后基于简单的 is_same
检查传递重载:
To answer your question, you can put all arguments into a tuple and pick out the last and test that one. Then pass on an overload based on a simple is_same
check:
template<class...Us>
void foo_impl(true_type,Us...); // last argument is int
template<class...Us>
void foo_impl(false_type,Us...); // last argument non-int
template<class...Us>
void foo( Us&&...us ) {
using tuple=tuple<Us...>;
using last=decltype(get<sizeof...(Us)-1>(declval<tuple>()));
foo_impl(is_same<decay_t<last>,int>{}, forward<Us>(us)...);
}
这篇关于当可变参数模板不是最后一个参数时,如何重载它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!