2017-09-25 86 views
1

如何创建一个模板函数,它返回INDEX'th参数?返回INDEX'th参数的模板函数

template <int INDEX, typename ...PARAMETERS> 
auto &&select(PARAMETERS&& ...parameters); 

我知道一个“重量级”的解决方案:

template <int INDEX, typename ...PARAMETERS> 
auto &&select(PARAMETERS&& ...parameters) { 
    std::tuple<PARAMETERS&&...> t(parameters...); 
    return std::get<INDEX>(t); 
} 

我真的不喜欢这种解决方案,因为它严重依赖于编译器优化。此外,由于不必要的元组,它可能会减慢调试版本的速度。

或者我知道一个不是非常可扩展的(但性能-OK)解决方案:

template <int INDEX> 
struct SelectNthParameter; 

template <> 
struct SelectNthParameter<0> { 
    template <typename PAR0, typename ...TAIL> 
    static PAR0 &&value(PAR0 &&par0, TAIL&& ...tail) { 
     return forward<PAR0>(par0); 
    } 
}; 

template <> 
struct SelectNthParameter<1> { 
    template <typename PAR0, typename PAR1, typename ...TAIL> 
    static PAR1 &&value(PAR0 &&par0, PAR1 &&par1, TAIL&& ...tail) { 
     return forward<PAR1>(par1); 
    } 
}; 
// add more template specializations for 2...inf 

有没有更好的(更轻巧,可扩展性),对于这个问题的解决方案?

+0

您可能需要一个递归模板 - '<0>'的特例,以及使用'INDEX-1'调用自身的一般情况。这就是'std :: get'的实现方式。最后,我怀疑它会产生与“重量级”方法完全相同的代码。 –

回答

0

这就是我想出了,没有什么惊天动地:

template <int INDEX> 
struct SelectNthParameter { 
    template <typename HEAD, typename ...TAIL> 
    __attribute__((always_inline)) 
    static auto &&value(HEAD &&head, TAIL &&...tail) { 
     return SelectNthParameter<INDEX-1>::value(tail...); 
    } 
}; 

template <> 
struct SelectNthParameter<0> { 
    template <typename HEAD, typename ...TAIL> 
    __attribute__((always_inline)) 
    static auto &&value(HEAD &&head, TAIL &&...) { 
     return std::forward<HEAD>(head); 
    } 
}; 

因为always_inline,这种解决方案比tuple更有效率(在调试版本,是对每个参数只产生2汇编指令,更小于tuple版本)。

我可以更确定这将在发布版本中进行优化。我对这个解决方案也不是100%满意,但是这比问题中的例子要好。