C++ 非递归获取可变模板的最后一种类型的泛型类型特征? 注:

C++ 非递归获取可变模板的最后一种类型的泛型类型特征? 注:,c++,c++17,variadic-templates,template-meta-programming,typetraits,C++,C++17,Variadic Templates,Template Meta Programming,Typetraits,这里我关心的是编译速度 我假设递归类型特征通常比备选类型慢(如果可能的话)。如果我错了,请告诉我 我们可以访问变量列表前面的类型,无需递归,如下所示: #include <iostream> #include <type_traits> template <typename T> struct this_type { using type = T; }; template <typename T1, typename ...> str

这里我关心的是编译速度

我假设递归类型特征通常比备选类型慢(如果可能的话)。如果我错了,请告诉我


我们可以访问变量列表前面的类型,无需递归,如下所示:

#include <iostream>
#include <type_traits>

template <typename T>
struct this_type
{
    using type = T;
};

template <typename T1, typename ...>
struct front : this_type<T1> {};

template <typename ... Ts>
using front_t = typename front<Ts...>::type;

template <typename ... Ts>
void Foo ()
{
    std::cout << std::is_same_v<front_t<Ts...>, int> << std::endl;
}

int main ()
{
    Foo<int, char, bool>();
}
#包括
#包括
模板
构造此类型
{
使用类型=T;
};
模板
结构前端:此_类型{};
模板
使用front\u t=typename front::type;
模板
void Foo()
{

std::cout我会利用
std::tuple
来完成大部分繁重的工作

template<typename... Ts>
using back_t = std::tuple_element_t<std::tuple<Ts...>, sizeof...(Ts) - 1>;
模板
使用back\u t=std::tuple\u元素\u t;

Hmm。这或多或少是我用自己的版本a tuple(doh!)所做的。但是这并不能完全回答问题。我只是看了看
cppref
,它们的“可能实现”使用了头优先递归,所以在后面推断类型可能很慢。()@Elliott您可以深入了解供应商的
以了解他们的实际操作。这被称为“可能实施”而不是“强制实施”从GCC 10来看,它也是递归的。这也不能让我相信这是不可能的,因为如果可以从后面访问,那么
tuple\u元素\u t
仍然没有强烈的动机使用它,因为它的用户同样可能从前面访问(您可以使用一些条件,其中if
index>size/2
然后从后面访问,但考虑到额外的开销很小,特别是在小变量中,这可能不值得从速度增益中获得)。因此,我的问题被标记为重复-其中一些答案显示了如何获得
O(log(n))
c++11
中的递归,以及
c++17
中的
O(1)
,但我想我应该指出,
std::tuple\u元素
gcc
clang
中都是通过递归实现的(我还没有检查
msvc
)因此,在修复之前应该避免。它非常慢。请参阅Julius回答:仅供参考,我已经在
msvc
上测试了
std::tuple\u element\t
,它也是递归的,而且更重要的是,比其他方法慢得多。据我所知,这是一个重复。如果我遗漏了什么,请告诉我我知道,我会投票重新开放。@cigen,你是对的。这个问题还有一个很有希望的答案。谢谢!
template <typename ...>
struct back;

template <typename T1>
struct back <T1> : this_type<T1> {};

template <typename T1, typename T2>
struct back <T1, T2> : this_type<T2> {};

template <typename T1, typename T2, typename T3>
struct back <T1, T2, T3> : this_type<T3> {};

template <typename ... Ts>
using back_t = typename back<Ts...>::type;

template <typename ... Ts>
void Foo ()
{
    std::cout << std::is_same_v<back_t<Ts...>, bool> << std::endl;
}

int main ()
{
    Foo<int, char, bool>();
}
template<typename... Ts>
using back_t = std::tuple_element_t<std::tuple<Ts...>, sizeof...(Ts) - 1>;