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.
UPDATE
c++17 introduced "P0127R2 Declaring non-type template parameters with auto", allowing to declare a non-type template parameter(s) with auto
as a placeholder for the actual type:
template <auto P> struct Ptr {};
That is, P
is a non-type template parameter. Its type can be inferred with decltype(P)
.
auto
in a template parameter list is subject to well-known deduction and partial ordering rules. In your case, the type can be constrained to accept pointers only:
template <auto* P> struct Ptr {};
Note that the syntax utilizing auto
is sufficient even for more detailed inspection, e.g.:
template <typename F>
struct FunctionBase;
template <typename R, typename... Args>
struct FunctionBase<R(*)(Args...)> {};
template <auto F>
struct Function : FunctionBase<decltype(F)> {};
It's also possible to use the inferred type as a contraint for other template parameters:
template <auto I, decltype(I)... Is>
struct List {};
Old answer
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With