c++ - 这种获取模板参数包中最后一个元素的方法是否有隐藏的开销?

标签 c++ c++11 variadic-templates variadic-functions

我有一个带有不同参数的集合函数,但它们的最后一个元素都相同。所以我需要访问函数中的最后一个参数。环顾四周,我发现了很多具有模板特化的解决方案( herehere ),但我想到了这个解决方案:

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/

相关文章:

c++ - 循环中的 Poco ScopedLock

c++ - 我们应该使用标准库中的异常类型吗?

c++ - 为什么 gcc 仅针对统一初始化警告缩小转换?

c++ - 将成员函数指针转换为普通函数指针

c++ - 将N-arg函数包装到另一个函数中

c++ - Cpp线程对象和shared_ptr问题

javascript - 在 Node.js 插件中使用 std::thread

c++ - 为什么对原始类型的操作是无序的而不是不确定的顺序?

c++11 - std::move 与 lambda 中的 std::shared_ptr

c++ - 带有可变参数模板类的 SFINAE?