Author Topic: mingw32-g++ is special to template parameter type convert ?  (Read 4260 times)

Offline leeya

  • Multiple posting newcomer
  • *
  • Posts: 16
mingw32-g++ is special to template parameter type convert ?
« on: April 16, 2007, 04:37:21 pm »
Handles.h has been defined:

#ifndef HANDLES_H
#define HANDLES_H

namespace Win {
    template<class NativeHandle, NativeHandle NullHandle = 0>
    class Handle
    {
        public:
            typedef NativeHandle Type;
            Handle (NativeHandle h =  NullHandle) : _native (h) {}
            bool IsNull () const throw () { return _native == NullHandle; }
            NativeHandle ToNative () const { return _native; }
            void Reset (NativeHandle h = NullHandle) { _native =  h;}
            bool operator== (Handle h) const { return _native == h.ToNative (); }
            bool operator!= (Handle h) const { return _native != h.ToNative (); }
            static NativeHandle NullValue () throw () { return NullHandle; }
        protected:
            NativeHandle H () const { return _native; }
            NativeHandle & BaseHRef () { return _native; }
        protected:
            NativeHandle _native;
    };

}


#endif // HANDLES_H


Instance.h has been defined:

#ifndef INSTANCE_H
#define INSTANCE_H

#include <Win/Handles.h>

namespace Win
{
   class Instance: public Win::Handle<HINSTANCE>   {
   public:
      Instance (HINSTANCE h = 0) : Win::Handle<HINSTANCE> (h) {}

   };
}


#endif // INSTANCE_H


After building my project, I get error message of type convert:

D:\CodeWorld\RSWL2GCC\Win\Instance.h:9: error: could not convert template argument `0' to `HINSTANCE__*'
D:\CodeWorld\RSWL2GCC\Win\Instance.h:11: error: could not convert template argument `0' to `HINSTANCE__*'
:: === Build finished: 2 errors, 0 warnings ===


It was successful for VS2003.net, why failed in MingW ?

Offline TDragon

  • Lives here!
  • ****
  • Posts: 943
    • TDM-GCC
Re: mingw32-g++ is special to template parameter type convert ?
« Reply #1 on: April 16, 2007, 05:47:38 pm »
Try adding a static_cast to the template definition.

Nope, that doesn't work either. Thinking about C++ templates...

Final answer:
I'm stumped as to why your method doesn't work, but with some further thought I think it's also not the most correct way to do it. With your method, if you have a handle type where 0 isn't the correct null value, you would need to specify the appropriate null value every time you instantiate a handle of that type.

My solution: template specialization. Observe. (And please pardon the reformatting. I find it easier to think in my own coding style.)
Code
// This templated function handles creating appropriate null values for
// handles. Obviously. The default action is to assume that 0 makes an
// appropriate null.
template< class NativeHandle >
NativeHandle NullHandleFactory()
{
    return 0;
}


// Here is your handle class, pretty much unchanged except that we now
// call NullHandleFactory everywhere.
template< class NativeHandle >
class Handle
{
public:
    typedef NativeHandle Type;

    Handle(NativeHandle h = NullHandleFactory< NativeHandle >())
     : _native (h)
    {
    }

    bool IsNull() const throw()
    {
        return _native == NullHandleFactory< NativeHandle >();
    }

    NativeHandle ToNative() const { return _native; }

    void Reset (NativeHandle h = NullHandleFactory< NativeHandle >())
    {
        _native = h;
    }

    bool operator == (Handle h) const
    {
        return _native == h.ToNative();
    }

    bool operator != (Handle h) const
    {
        return _native != h.ToNative ();
    }

    static NativeHandle NullValue() throw()
    {
        return NullHandleFactory< NativeHandle >();
    }

protected:
    NativeHandle H() const { return _native; }
    NativeHandle& BaseHRef() { return _native; }

protected:
    NativeHandle _native;
};


// Here is your regular old HINSTANCE handle. The unspecialized
// NullHandleFactory is appropriate here, since HINSTANCE's are pointers
// and 0 is a good pointer value.
class Instance: public Handle< HINSTANCE >
{
public:
    Instance(HINSTANCE h = 0)
     : Handle< HINSTANCE >(h)
    {
    }
};


// But here's a type that is NOT implicitly convertible from 0.
struct NoZerosAllowed
{
};

// So what do we do? We specialize the NullHandleFactory template function
// for this specific type to return something appropriate.
template<>
NoZerosAllowed NullHandleFactory()
{
    return NoZerosAllowed();
}

// Now our FunkyHandle class can treat NoZerosAllowed handles just like
// other handles
class FunkyHandle : public Handle< NoZerosAllowed >
{
public:
    // If we hadn't specialized NullHandleFactory, an error would be thrown here
    // because we're using Handle's default constructor, which calls
    // NullHandleFactory
    FunkyHandle()
    {
    }
};
« Last Edit: April 16, 2007, 07:10:59 pm by TDragon »
https://jmeubank.github.io/tdm-gcc/ - TDM-GCC compiler suite for Windows (GCC 9.2.0 2020-03-08, 32/64-bit, no extra DLLs)

Offline leeya

  • Multiple posting newcomer
  • *
  • Posts: 16
Re: mingw32-g++ is special to template parameter type convert ?
« Reply #2 on: April 17, 2007, 03:57:00 pm »
 :D

Thanks for your wonderful solution~~~ I can benifit from your solution.