更新
c++17 引入了“P0127R2 Declaring non-type template parameters with auto”,允许用auto 作为实际类型的占位符来声明一个非类型模板参数:
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; 这样的模板声明,这样我们就可以实例化像C<&X::f> 这样的模板,而不必说C<decltype(&X::f), &X::f>。
基本思想是能够说出template<using typename T, T t> struct C {/* ... */}; 来表示应该推导出T。为了更详细地描述,我们考虑了模板类和函数的一些扩展示例。
[...]
关键思想是传递第二个模板参数的类型是多余的信息,因为它可以通过第二个类型参数的普通类型推导来推断。考虑到这一点,我们建议在模板参数前面加上 using 表示它不应该作为模板参数显式传递,而是从后续的非类型模板参数推导出来。这立即使我们能够提高describe_field 的可用性,如下所示。
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)
N3405 Template Tidbits中包含一个类似的提案:
两个人的T
激励的例子是一个假定的反射类型特征,它给出了类成员的属性。
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
问题是“describe 的声明应该是什么样子?” 由于它需要一个非类型模板参数,我们需要使用熟悉的(100k hits on谷歌)“template<class T, T t>”成语
template<typename T, T t> struct describe;
[...]
我们的关键思想是传递第二个模板参数的类型是(几乎总是)冗余信息,因为可以使用第二个类型参数的普通类型推导来推断它。考虑到这一点,我们建议允许 describe 声明如下。
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)
可以在EWG issue 9 下跟踪两个提案的当前状态。
还有一些其他discussions 提出了auto 的替代语法:
template <auto T> struct describe;