我在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。
答案 0 :(得分:12)
<强>更新强>
c++17介绍&#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月,c++14),不可能
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