c ++模板参数类型推断 [英] c++ template parameter type inference
问题描述
我在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 likeC<&X::f>
instead of having to sayC<decltype(&X::f), &X::f>
.The basic idea is to be able to say
template<using typename T, T t> struct C {/* ... */};
to indicate thatT
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>"
idiomtemplate<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屋!