c ++模板参数类型推断

时间:2014-12-09 06:09:04

标签: c++ templates type-inference inferred-type

我在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类型部分。

如何声明我的模板呢?

我已经阅读了这个问题,但答案是使用宏,这并不好: template of template c++?

我可以通过没有宏的模板来做到这一点吗?我正在使用Visual C ++ 2013。

1 个答案:

答案 0 :(得分:12)

<强>更新

介绍&#34; P0127R2 Declaring non-type template parameters with auto&#34;,允许声明一个非auto的非类型模板参数作为实际类型的占位符:< / p>

template <auto P> struct Ptr {};

即,P是非类型模板参数。其类型可以用decltype(P)推断。

模板参数列表中的

auto遵循众所周知的推理和部分排序规则。在您的情况下,类型可以被约束为仅接受指针:

template <auto* P> struct Ptr {};

请注意,即使是更详细的检查,使用auto的语法也足够了,例如:

template <typename F>
struct FunctionBase;

template <typename R, typename... Args>
struct FunctionBase<R(*)(Args...)> {};

template <auto F>
struct Function : FunctionBase<decltype(F)> {};

也可以使用推断类型作为其他模板参数的约束力:

template <auto I, decltype(I)... Is>
struct List {};

旧答案

由于您在没有宏定义帮助的情况下询问基于纯类模板的解决方案,因此答案很简单:至于现在(2014年12月,),不可能

WG21 C ++标准委员会已将此问题确定为需要,并且有几个建议让模板自动推断非类型模板参数的类型。

最接近的是N3601 Implicit template parameters

  

隐式模板参数

     

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

     

目标是能够将template<typename T, T t> struct C;之类的模板声明替换为另一个声明,以便我们可以像[{1}}那样即时发布模板,而不必说C<&X::f>

     

基本想法是能够说出C<decltype(&X::f), &X::f>来表明应该推断template<using typename T, T t> struct C {/* ... */};。为了更详细地描述,我们考虑了模板类和函数的一些扩展示例。

     

[...]

     

关键思想是传递第二个模板参数的类型是冗余信息,因为它可以使用来自第二个类型参数的普通类型推导来推断。考虑到这一点,我们建议使用using前缀模板参数表明它不应该作为模板参数显式传递,而是从后续的非类型模板参数推导出来。这立即使我们能够提高T的可用性,如下所示。

describe_field

类似的提案是N3405 Template Tidbits中包含的提案:

  

T为两个

     

激励性的例子是一个假定的反射类型特征,它给出了一个类成员的属性。

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)
     

问题是&#34;描述的声明应该是什么样的?&#34; 因为它需要非类型模板参数,所以我们需要使用参数的类型来指定熟悉的(谷歌上的10万次点击)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 成语

“template<class T, T t>”
     

[...]

     

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

describe

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

还有一些其他discussions建议使用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) 替代语法:

auto