www.digitalmars.com         C & C++   DMDScript  

c++ - Funky template bug - a trimmed down example

reply "Matthew Wilson" <matthew stlsoft.org> writes:
Walter, as promised, here's a trimmed down example (an extract from COMSTL).
It's still not tiny, but is self-contained and as small as can be. This code
works with Borland (5.5, 5.6), Intel (6 & 7), VC++ (5, 6, 7), G++ (2.95 &
3.2), Metrowerks CodeWarrior (7 & 8).


#include <windows.h>

#include <algorithm>
#include <functional>

#ifndef __DMC__
using std::unary_function;
using std::for_each;
#endif /* __DMC__ */

template<typename R, typename T>
class std_mem_fun_t
    : public unary_function<T*, R>
{
public:
    typedef R (STDAPICALLTYPE T::*method_type)();

public:
    explicit std_mem_fun_t(method_type pmfn)
        : m_f(pmfn)
    {}

    R operator ()(T *pt) const
    {
        return (pt->*m_f)();
    }

private:
    method_type m_f;
};

template <class R, class T>
inline std_mem_fun_t<R, T> std_mem_fun(R (STDAPICALLTYPE T::*f)())
{
    return std_mem_fun_t<R, T>(f);
}


int main()
{
    // Dimension of the array
    const int   C_UNKNOWNS  =   10;

    // This is the CLSID for the GIT, though it could be anything really
    static const CLSID _CLSID_WidelyAvailableStdObject =
    {
            0x00000323
        ,   0x0000
        ,   0x0000
        ,   { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }
    };

    ::CoInitialize(NULL);

    LPUNKNOWN   unknowns[C_UNKNOWNS];

    // Create them
    for(int i = 0; i < C_UNKNOWNS; ++i)
    {
        if(FAILED(::CoCreateInstance(   _CLSID_WidelyAvailableStdObject,
                                        NULL,
                                        CLSCTX_ALL,
                                        IID_IUnknown,

reinterpret_cast<void**>(&unknowns[i]))))
        {
            unknowns[i] = NULL;
        }
    }

    LPUNKNOWN   *begin  =   unknowns;
    LPUNKNOWN   *end    =   begin + C_UNKNOWNS;

    // Doesn't work for temporaries here ...
    for_each(begin, end, std_mem_fun(&IUnknown::Release));

    // ... or in explicit form either
    std_mem_fun_t<ULONG, IUnknown>  fn(&IUnknown::Release);

    ::CoUninitialize();

    return 0;
}
May 20 2003
parent Richard Grant <fractal clark.net> writes:
    typedef R (STDAPICALLTYPE T::*method_type)();
useful for external chatter since no "typdef template <class.." :-(.
    explicit std_mem_fun_t(method_type pmfn)
        : m_f(pmfn)
explicit std_mem_fun_t(R (STDAPICALLTYPE T::*pmfn)()) : m_f(pmfn) Something amiss with typdef inside the class here.. since specific reference to the member function pointer works.
    method_type m_f;
R ( STDAPICALLTYPE T::*m_f)(); Still something wrong with typedef on template member pointers here, but this works. So someone needs to give Walter a targeted test case with member function pointer typedefs in template classes, since they are probably getting the wrong sig. I don't have all the cocreate stuff, but this compiled for me. Richard
May 20 2003