我有一个带有不同参数的集合函数,但它们的最后一个元素都相同。所以我需要访问函数中的最后一个参数。环顾四周,我发现了很多具有模板特化的解决方案( here 和 here ),但我想到了这个解决方案:
template<typename ...Args>
void function( Args&&... args )
{
auto &last = std::get<sizeof...( Args ) - 1 >( std::tie( args... ) );
}
这可能看起来很明显,但一开始对我来说并非如此。它看起来简单而简短,但与具有模板特化和辅助函数/类的经典解决方案相比,这种方法是否有任何隐藏的开销?
最佳答案
It seems to be simple and short, but does this method have any hidden overhead versus classic solutions with template specialization and helper functions/classes?
它有一个缺点,在某些情况下可能会很烦人。如果您的类型在成员方法上有引用限定符,您可能会在从中获取左值引用时遇到问题。
让我们考虑以下示例:
#include<utility>
#include<tuple>
struct S {
void foo() && {}
};
template<typename T>
void f(T &&t) {
std::forward<T>(t).foo();
}
int main() {
f(S{});
}
一切正常,因为我们最初有一个右值引用,通过转发转发引用,我们可以安全地调用 foo
成员方法。
现在让我们考虑一下您的代码片段(请注意,以下代码无法编译 - 继续阅读):
#include<utility>
#include<tuple>
struct S {
void foo() && {}
};
template<typename... T>
void g(T&&... t) {
auto &last = std::get<sizeof...(T) - 1 >(std::tie(t...));
last.foo();
}
int main() {
g(S{});
}
由于引用限定符,这不会编译为 foo
不能再在类型为 S &
的变量上调用。
另一方面,通过以某种方式转发和提取最后一个参数,您可以保持其类型不变,并且不会遇到这样的问题。
例如:
template<typename... T>
void g(T&&... t) {
std::get<sizeof...(T) - 1>(std::forward_as_tuple(std::forward<T>(t)...)).foo();
}
关于c++ - 这种获取模板参数包中最后一个元素的方法是否有隐藏的开销?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45867888/