tags:

views:

81

answers:

2

Hello,

I'm trying to replicate a template I've used before with a member function, and it isn't going very well. The basic form of the function is

template<class T>
T Convert( HRESULT (*Foo)(T*))
{
    T temp;
    Foo(&temp); //Throw if HRESULT is a failure
    return temp;
}

HRESULT Converter(UINT* val)
{
    *val = 1;
    return S_OK;
}


int _tmain(int argc, _TCHAR* argv[])
{
    std::cout << Convert<UINT>(Converter) << std::endl;
    return 0;
}

For the life of me, I can't get this to work with a member variable. I've read up on their syntax, and I can't seem to figure out how to make it work with templates.

The class would be something similar to

class TestClass
{ 
    HRESULT Converter(UINT* val)
    {
      *val = 1;
      return S_OK;
    }

}
+5  A: 

TestClass is stateless. So why do you want to pass a non-static member function? If in the real code you need access to non-static members, you also need to pass the object along

template<class T, class C>
T Convert( HRESULT (C::*Foo)(T*), C c)
{
    T temp;
    (c.*Foo)(&temp); //Throw if HRESULT is a failure
    return temp;
}

You can then call it like the following, assuming the member function is made public

TestClass c;
Convert(&TestClass::Converter, c);

If the class is heavy-weight or if the function changes its object during execution, you may decide to pass the object to Convert by reference.

Johannes Schaub - litb
Or if he can use std::tr1::function, he can get by with a single method that handles both member functions and free functions.
Ben
@Ben good point. I think using `function` should be preferred.
Johannes Schaub - litb
@Ben, what would that one look like?
Steve
Oh, TestClass is only stateless as an example. RealClass actually has a ton of state
Steve
+2  A: 

Here's the implementation using std::tr1::function.

#include <stdlib.h>
#include <functional>
#include <iostream>
#include <winerror.h>
#include <wtypes.h>

using std::tr1::bind;
using std::tr1::function;

template <typename T>
T Convert(function<HRESULT (T*)> Converter)
{
    T temp;
    Converter(&temp);
    return temp;
}

HRESULT Converter(UINT* val)
{
    *val = 1;
    return S_OK;
}

class TestClass
{
public:
    HRESULT Converter(UINT* val)
    {
        *val = 2;
        return S_OK;
    }
};

int main()
{
    using namespace std::tr1::placeholders;

    std::cout << Convert<UINT>(Converter) << std::endl;

    TestClass converter;
    std::cout << Convert<UINT>(bind(&TestClass::Converter, converter, _1)) << std::endl;

    return EXIT_SUCCESS;
}
Ben