Wal*_*Cat 10 c++ templates type-inference inferred-type
我在C++中有这样的模板
template<typename T, T* P> struct Ptr {};
Run Code Online (Sandbox Code Playgroud)
所以我可以这样使用它:
const int i = 0;
Ptr<int, &i> ptr;
Run Code Online (Sandbox Code Playgroud)
要么
Ptr<decltype(i), &i> ptr;
Run Code Online (Sandbox Code Playgroud)
但我不想两次指定类型int或标识i,我只想使用
Ptr<&i> ptr;
Run Code Online (Sandbox Code Playgroud)
让编译器自己找出int类型部分.
如何声明我的模板呢?
我已经阅读了这个问题,但答案是使用宏,这不是很好: 模板c ++的模板?
我可以通过没有宏的模板来做到这一点吗?我正在使用Visual C++ 2013.
Pio*_*cki 12
UPDATE
c ++ 17引入了" P0127R2使用auto声明非类型模板参数 ",允许声明非类型模板参数auto作为实际类型的占位符:
template <auto P> struct Ptr {};
Run Code Online (Sandbox Code Playgroud)
也就是说,P是非类型模板参数.它的类型可以推断出来decltype(P).
auto在模板参数列表中受到众所周知的推论和部分排序规则的约束.在您的情况下,类型可以被约束为仅接受指针:
template <auto* P> struct Ptr {};
Run Code Online (Sandbox Code Playgroud)
请注意,auto即使是更详细的检查,语法利用也足够了,例如:
template <typename F>
struct FunctionBase;
template <typename R, typename... Args>
struct FunctionBase<R(*)(Args...)> {};
template <auto F>
struct Function : FunctionBase<decltype(F)> {};
Run Code Online (Sandbox Code Playgroud)
也可以使用推断类型作为其他模板参数的约束:
template <auto I, decltype(I)... Is>
struct List {};
Run Code Online (Sandbox Code Playgroud)
老答案
由于您在没有宏定义帮助的情况下询问基于纯类模板的解决方案,因此答案很简单:就目前而言(2014年12月,c ++ 14),这是不可能的.
这个问题已经被WG21 C++标准委员会确定为需要,并且有几个建议让模板自动推断非类型模板参数的类型.
最接近的是N3601隐式模板参数:
隐式模板参数
这个例子的目的是消除冗余
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如下的可用性.Run Code Online (Sandbox Code Playgroud)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模板花絮中包含的提议:
T两个
激励的例子是一个假定的反射类型特征,给出了一个类成员的属性.
Run Code Online (Sandbox Code Playgroud)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问题是"描述的声明应该是什么样的?" 由于它采用非类型模板参数,我们需要使用熟悉的(在Google上点击100k)
“template<class T, T t>”成语来指定参数的类型Run Code Online (Sandbox Code Playgroud)template<typename T, T t> struct describe;[...]
我们的关键思想是传递第二个模板参数的类型(几乎总是)冗余信息,因为它可以使用来自第二个类型参数的普通类型推导来推断.考虑到这一点,我们建议允许
describe声明如下.Run Code Online (Sandbox Code Playgroud)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第9期跟踪这两个提案的当前状态.
还有一些其他讨论提出了替代语法auto:
template <auto T> struct describe;
Run Code Online (Sandbox Code Playgroud)