Reputation: 4907
Note: this question is largely academic.
We can use a pointer-to-member as a template parameter in a class template, but if the "dependant" types are not known we must declare all of them as template parameters. For examples:
// Our template operates with a "pointer to member", but it's generic for
// both the type of the member value itself, as well as the owner type of
// which the value is a member.
template <class T, class V, V T::*memptr>
struct Foo {};
In this case we must include T
, V
as template parameters if the template functionality is generic over these types. Usage of this template seems rather verbose, however:
struct Bar {int a;};
struct Baz {double a;};
int main(int argc, char** argv) {
// The first two parameters "Bar, int" are kinda redundant
Foo<Bar, int, &Bar::a> foo1;
// Same here with Baz, double
Foo<Baz, double, &Baz::a> foo2;
}
In particular the template parameter &Bar::a
is a non-type parameter whose type is int &Bar::*
. Thus, it seems that T=Bar, V=int
is quite obvious.
Is there a syntax, metaprogram, or construct that can be exploited so that we can instantiate the template with only memptr=&Bar::a
and allow T=Bar, V=int
to be deduced/inferred?
Ideally we would instantiate the template with simply:
Foo<&Bar::a> foo1;
Foo<&Baz::a> foo2;
But I can't seem to figure out a way to achieve this. I have a solution that utilizes a preprocessor macro:
// This is an ugly metaprogram and macro to shorten-up usages of the template
template <class T, class V>
struct Step2 {
template <V T::*memptr>
struct Step3 {
typedef Foo<T, V, memptr> Type;
};
};
template <class T, class V>
Step2<T, V> step1(V T::*memptr);
#define FOO(T, MEMBER) decltype(step1(&T::MEMBER))::Step3<&T::MEMBER>::Type
Which can be used as:
int main(int argc, char** argv) {
// It seems that thre should be a more compact way to instantiate this
// template. Indeed the macro does this, but macros are tough because they're
// global names and it can make compiler errors really tough to comprehend.
FOO(Bar, a) foo1;
FOO(Baz, a) foo2;
}
But this does not seem like a problem that needs preprocessor macros as a solution.
Upvotes: 0
Views: 40
Reputation: 4079
Similar question: Deducing pointer-to-member template arguments
The answer from there is to lean on C++17 auto magic:
template <auto p>
struct Foo {};
Upvotes: 1