How to reduce template arguments?

c++, templates

Solution

I just wouldn't store the member pointer as a template argument:

template<class T, class Foo>
struct X {
    X(T Foo::*p): p(p) {}
    void operator()(Foo & f) {
        (f.*p) = 12 * (f.*p);   // simple example. could be more complex `operator()`
    }
private:
    T Foo::*p;
};

template <class T, class Foo>
X<T, Foo> MakeX(T Foo::*p)
{
    return p;
}

I don't think it is possible to deduce the types with your approach: you can't use a pointer-to-member passed to a function which is where the type deduction occurs.

Edit: There may be macro-based solutions, though.

For example, you can make a class to create X instances, like this:

template <class T, class Foo>
struct XMaker
{
    template <T Foo::*p>
    X<T, Foo, p> make() { return X<T, Foo, p>(); }
};

Now, you can create a make... function to deduce T and Foo:

template <class T, class Foo>
XMaker<T, Foo> make_x_maker(T Foo::*)
{
    return XMaker<T, Foo>();
}

Which makes it possible to write a macro like:

#define CREATE_X(member) make_x_maker(member).make<member>()

Usage:

std::for_each(cont.begin(), cont.end(), CREATE_X(&FF::r) );

Problem

Here I have functor of the follow kind: ``` template<class T, class Foo, T Foo::*p> struct X { void operator()(Foo & f) { (f.*p) = 12 * (f.*p); // simple example. could be more complex `operator()` } }; ``` And sample struct: ``` struct FF { int m; int r; }; ``` I want to use the functor X, but I don't want to explicitly specify template argument as follows: ``` void testforx() { std::vector<FF> cont(5); std::for_each(cont.begin(), cont.end(), X<int, FF, &FF::r>() ); // it work, but I don't want to write `int` and `FF` std::for_each(cont.begin(), cont.end(), createx<&FF::r>() ); // how I would like to use it, how to declare `createx` function? } ``` Here what I tried with no success: ``` // that is what I tried, but it could not deduce T and Foo template<T Foo::*p, class T, class Foo> X<T, Foo, T Foo::*p> createx() { return X<T, Foo, p>(); } // this works, but requires to write T and Foo explicitly template<class T, class Foo, T Foo::*p> X<T, Foo, T Foo::*p> createx() { return X<T, Foo, p>(); } ```

Original source

Related problems