std :: tuple_element需要深度模板实例化 [英] std::tuple_element need deep template instantination

查看:143
本文介绍了std :: tuple_element需要深度模板实例化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此处 http://en.cppreference.com/w/cpp/Utility/tuple/tuple_element 给出了std :: tuple_element的可能实现.

 template< std::size_t I, class T >
struct tuple_element;

// recursive case
template< std::size_t I, class Head, class... Tail >
struct tuple_element<I, std::tuple<Head, Tail...>>
    : std::tuple_element<I-1, std::tuple<Tail...>> { };

// base case
template< class Head, class... Tail >
struct tuple_element<0, std::tuple<Head, Tail...>> {
   typedef Head type;
};

但是,如果元组具有很多参数(超过100个或200个参数),则此实现需要深度递归实例化.

Q1:为什么C ++ 11没有添加用于通过索引获取元素的特殊运算符? 像元组[2]或元组[0]吗?

Q2:可以减少深度实例化吗?例如,在D语言中,更多的模板算法(以typetuple形式)需要O(log(N))深度实例化.

问题1:为什么没有为C ++ 11添加特殊运算符来从可变参数模板中通过索引获取元素? 像模板< class ... T>结构索引{typedef T [3] third_element;}

解决方案

为什么没有为要通过索引获取元素的C ++ 11添加特殊运算符?像元组 2 或元组[0]吗?

首先,因为即使他们这样做了,它仍然可以以相同的方式工作:使用递归.元组主要是一个 library 功能.尽管它们背负了可变参数模板之类的语言功能,但它们在C ++ 98/03中或多或少地发挥了作用.

第二,将不可能.并非没有非常困难的语言更改.

您不清楚tuple[2]是什么意思.

如果您的意思是std::tuple<int, float, std::string>[2]应该以某种方式解析为类型名称std::string,那么这意味着您现在需要解释为什么这样做.同样,元组是一个功能,而不是一种语言构造.因此,必须有某种语言构造,其中typename[integer]是有效的构造.那是什么意思?

如果您的意思是给定的:

std::tuple<int, float, std::string> tpl{...};

我们应该能够使用tpl[2]来获取字符串,即几个阴影中的不会发生". C ++是一种静态类型的语言. std::get之所以能够做到这一点,唯一的原因是整数索引不是函数参数;它不是整数.它是一个 template 参数.这就是允许std::get<0>返回与std::get<2>完全不同的类型的原因. operator[](int)不会发生这种情况;该函数必须始终返回相同的类型.

所以现在您需要类似template<class T, int i> ... operator[]()的东西.这将非常令人困惑,因为您不能再对该类型执行tpl[runtimeValue](因为模板参数必须是编译时值).没有这样的类型,其中operator[]受限制不能使用运行时值.因此,您将创建一个非常奇数球类型.

即使这样...它仍然必须递归来获取值.

是否可以减少深度实例化?

在编译时间之外(这不是一个不合理的问题),这有什么关系?像样的衬里将把它们中的大多数扔掉.

关于编译时间,std::tuple的各种功能有非递归实现.他们是否可以非递归地执行tuple_element,我不这样认为. 此libc ++实现似乎表明http://en.cppreference.com/w/cpp/utility/tuple/tuple_element given possible implementation of std::tuple_element.

 template< std::size_t I, class T >
struct tuple_element;

// recursive case
template< std::size_t I, class Head, class... Tail >
struct tuple_element<I, std::tuple<Head, Tail...>>
    : std::tuple_element<I-1, std::tuple<Tail...>> { };

// base case
template< class Head, class... Tail >
struct tuple_element<0, std::tuple<Head, Tail...>> {
   typedef Head type;
};

But, this implementation need deep recursion instantiation, if tuple has a lot parameters ( more that 100 or 200 parameters).

Q1: Why C++11 was not added special operator for getting elements by index? like tuple[2] or tuple[0] ?

Q2: Is possible reduce the deep instantiation? For example in D language more template algorithms (in typetuple) needed O(log(N) ) deep instantiation.

EDIT: Q1: Why C++11 was not added special operator for getting elements by index from variadic templates? like template< class ...T> struct index{ typedef T[3] third_element;}

解决方案

Why C++11 was not added special operator for getting elements by index? like tuple2 or tuple[0] ?

First, because even if they did, it'd still work the same way: with recursion. Tuples are primarily a library feature. Though they piggy-back off of language features like variadic templates, they were more or less functional in C++98/03.

Second, that would not be possible. Not without a very difficult language change.

It's not clear what you mean by tuple[2].

If you mean that std::tuple<int, float, std::string>[2] should somehow resolve to the typename std::string, then that means you now need to explain why this works. Again, tuples are a library feature, not a language construct. So there would have to be some language construct whereby typename[integer] is a valid construct. What would that be and what would it mean?

If you mean that given:

std::tuple<int, float, std::string> tpl{...};

We should be able to get the string with tpl[2], that's several shades of "not going to happen". C++ is a statically typed language. The only reason std::get is able to get away with what it does is that the integer index is not a function parameter; it is a template parameter. That is what allows std::get<0> to return a completely different type from std::get<2>. That can't happen with operator[](int); that function must always return the same type.

So now you'd need to have something like template<class T, int i> ... operator[](). And that would be very confusing, because you can no longer do tpl[runtimeValue] on that type (since template parameters must be compile-time values). There is no such type where operator[] is restricted from being able to work on runtime values. So you'd be creating a very oddball type.

And even then... it would still have to do recursion to get the value.

Is possible reduce the deep instantiation?

Outside of compile times (which is not an unreasonable issue), what does it matter? A decent inliner will throw most of them away.

As for compile times, there are non-recursive implementations of various features of std::tuple. Whether they can do tuple_element non-recursively, I don't think so. This libc++ implementation seems to suggest that it can't, despite implementing the tuple itself non-recursively.

这篇关于std :: tuple_element需要深度模板实例化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆