c ++模板参数类型推断 [英] c++ template parameter type inference

查看:178
本文介绍了c ++模板参数类型推断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在C ++中有这样的模板

  template< typename T,T * P& struct Ptr {}; 

所以我可以这样使用:

  const int i = 0; 
Ptr< int,& i> ptr;

  Ptr< decltype(i),& i> ptr; 

但我不想指定类型 int 或身份 i 两次,我想只使用

  Ptr<& i> ptr; 

,让编译器找出 int



我已经阅读了这篇文章问题,但答案是使用宏,这不是很好:
模板c ++模板?



我可以通过模板没有宏吗?我使用Visual C ++ 2013.

解决方案

因为你问一个纯类基于模板的解决方案没有宏的帮助定义,那么答案很简单:现在(2014年12月,C ++ 14)是不可能的



已经由WG21 C ++标准委员会确定为一个需求,并且有几个建议让模板自动推断非类型模板参数的类型。



最近的是 N3601隐式模板参数


隐式模板参数



此示例的目的是消除冗余 template< typename T,T t> idiom。这个成语被广泛使用,在Google上超过10万次点击。



目标是能够替换模板声明如 template< typename T ,T t> struct C; 与另一个声明,以便我们可以即时化像 C<& X :: f> 的模板,而不必说 C< decltype(& X :: f),& X :: f>



能够说模板<使用类型名T,T t> struct C {/ * ... * /}; ,表示应该推导出 T 。要更详细地描述,我们考虑一些模板类和函数的扩展示例。



[...]



关键思想是传递第二个模板参数的类型是冗余信息,因为它可以使用普通类型推导从第二个类型参数推断。考虑到这一点,我们建议使用前置模板参数表示它不应该作为模板参数显式传递,而是从后续的非类型模板参数中推导出来。这立即允许我们如下改进 describe_field 的可用性。

  template<使用类型名T,T t> struct describe_field {/ * ... * /}; 
/ * ... * /
cout< describe_field<& A :: f> :: name; // 好。 T是void(A :: *)(int)
cout<< describe_field<& A :: g> :: arity; // 好。 T是double(A :: *)(size_t)


类似的提案是 N3405模板Tidbits 中包含的类似提案: / p>


T两个



激励的例子是假定的反射类型特性

  struct A {
void f(int i);
double g(size_t s);
};
/ * ... * /
cout< describe<& A :: f> :: name; // Printsf
cout<< describe<& A :: g> :: arity; // prints 1

问题是描述的声明应该是什么样子? 由于它需要一个非类型的模板参数,我们需要使用熟悉的(在Google上100k点击)template< class T,T t> idiom

  template< typename T,T t& struct describe; 

[...]



关键思想是传递第二模板参数的类型是(几乎总是)冗余信息,因为它可以使用来自第二类型参数的普通类型推导来推断。考虑到这一点,我们建议允许 describe 声明如下。

  template< typename T t> struct describe; 
/ * ... * /
cout< describe<& A :: f> :: name; // 好。 T是void(A :: *)(int)
cout<< describe<& A :: g> :: arity; // 好。 T是double(A :: *)(size_t)


可以在 EWG问题9 下跟踪两个提案的当前状态。



还有一些讨论使用 auto

 code> template< auto T> struct describe; 


I have such a template in C++

template<typename T, T* P> struct Ptr {};

so I can use it as such:

const int i = 0;
Ptr<int, &i> ptr;

or

Ptr<decltype(i), &i> ptr;

But I don't want to specify the type int or identity i twice, I want to use just

Ptr<&i> ptr;

and let the compiler figure out the int type part by itself.

How can I declare my template to do that ?

I've read this question but the answer is using macros, that's not nice: template of template c++?

can I do this by just template without macros ? I'm using Visual C++ 2013.

解决方案

Since you are asking about a pure class template-based solution without the help of macro definitions then the answer is simple: as for now (Dec 2014, C++14) it is not possible.

This issue has been already identified by the WG21 C++ Standard Committee as a need and there are several proposals to let templates automatically infer the type of non-type template arguments.

The closest is N3601 Implicit template parameters:

Implicit template parameters

The purpose of this example is to eliminate the need for the redundant template<typename T, T t> idiom. This idiom is widely used, with over 100k hits on Google.

The goal is to be able to replace a template declaration like template<typename T, T t> struct C; with another declaration so that we can instantatiate the template like C<&X::f> instead of having to say C<decltype(&X::f), &X::f>.

The basic idea is to be able to say template<using typename T, T t> struct C {/* ... */}; to indicate that T should be deduced. To describe in more detail, we consider some extended examples of template classes and functions.

[...]

The key idea is that passing the type of the second template parameter is redundant information because it can be inferred using ordinary type deduction from the second type parameter. With that in mind, we propose that prefacing a template parameter with using indicates that it should not be passed explicitly as a template argument but instead will be deduced from subsequent non-type template arguments. This immediately allows us to improve the usability of describe_field as follows.

template<using typename T, T t> struct describe_field { /* ... */ };
/* ... */
cout << describe_field<&A::f>::name;   // OK. T is void(A::*)(int)
cout << describe_field<&A::g>::arity;  // OK. T is double(A::*)(size_t)

A similar proposal is the one included in N3405 Template Tidbits:

T for two

The motivating example is a putative reflection type trait giving properties of a class member.

struct A {
  void f(int i);
  double g(size_t s);
};
/* ... */
cout << describe<&A::f>::name;   // Prints "f"
cout << describe<&A::g>::arity;  // prints 1

The question is "what should the declaration of describe look like?" Since it takes a non-type template parameter, we need to specify the type of the parameter using the familiar (100k hits on Google) "template<class T, T t>" idiom

template<typename T, T t> struct describe;

[...]

Our key idea is that passing the type of the second template parameter is (nearly always) redundant information because it can be inferred using ordinary type deduction from the second type parameter. With that in mind, we propose allowing describe to be declared as follows.

template<typename T t> struct describe;
/* ... */
cout << describe<&A::f>::name;   // OK. T is void(A::*)(int)
cout << describe<&A::g>::arity;  // OK. T is double(A::*)(size_t)

The current status of both proposals can be tracked under EWG issue 9.

There are some other discussions proposing alternative syntax with auto:

template <auto T> struct describe;

这篇关于c ++模板参数类型推断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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