On 27 August 2012 11:28, Walter Bright <newshound2@digitalmars.com> wrote:
On 8/27/2012 1:08 AM, Manu wrote:

Also, I think it could be fixed so the scenario in the bug report worked as
expected (I still don't understand why it did't work in the first place).

Because the two types were considered to be the same, only different.

And how was that a problem? They never interacted in the example, the assignments were totally separate, they shouldn't have been confused.
Just speculating, but it just looks like the type was misrepresented when it was looked up from a map by name or something, and matched the wrong cached definition... or something along those lines.
It looks like a bug exposed from implementation detail, I can't see anything in the bug report that shouldn't theoretically work fine.

----------------------------------

Please post a canonical example of how you use this, so we can think of an alternative.

Well likewise, can you provide an example where, assuming that one bug were fixed, that the old approach actually caused a problem?
The bug report shows a situation that has a clear presumed behaviour, and could surely have just been fixed.



Almost all my API's are dynamically bound to foreign code, eg:

extern(C) void function( ref const(Vector2) v0, ref const(Vector2) v1, ref const(Vector2) v2, ref const(Color) color = Color.white, BlendMode blendMode = BlendMode.Disabled ) fillTriangle2D;
extern(C) void function( ref const(Vector3) v0, ref const(Vector3) v1, ref const(Vector3) v2, ref const(Color) color = Color.white, BlendMode blendMode = BlendMode.Disabled ) fillTriangle;
extern(C) void function( ref const(Vector2) vPosition, ref const(Vector2) vSizeref, ref BaseTexture texture, ref const(Color) color = Color.white, BlendMode blendMode = BlendMode.Disabled, TextureMode textureMode = TextureMode.AllChannels ) fillSprite;
extern(C) void function( ref const(Vector2) vMin, ref const(Vector2) vMax, ref const(Color) color = Color.white, BlendMode blendMode = BlendMode.Disabled ) fillRectangle;
extern(C) void function( ref const(Vector3) vMin, ref const(Vector3) vMax, ref const(Matrix4x3) mLocalToWorld = Matrix4x3.identity, ref const(Color) color = Color.white, BlendMode blendMode = BlendMode.Disabled ) fillBox;
extern(C) void function( ref const(Vector3) vCenter, float fRadius, ref const(Matrix4x3) mLocalToWorld = Matrix4x3.identity, ref const(Color) color = Color.white, BlendMode blendMode = BlendMode.Disabled, int iTessellationX = 12, int iTessellationY = 8 ) fillSphere;
extern(C) void function( float fLength, float fRadius, ref const(Matrix4x3) mLocalToWorld = Matrix4x3.identity, ref const(Color) color = Color.white, BlendMode blendMode = BlendMode.Disabled, int iTessellation = 10 ) fillCone;
extern(C) void function( float fLength, float fRadius1, float fRadius2, ref const(Matrix4x3) mLocalToWorld = Matrix4x3.identity, ref const(Color) color = Color.white, BlendMode blendMode = BlendMode.Disabled, int iTessellation = 10 ) fillCylinder;
extern(C) void function( ref const(Matrix4) mClipToWorld, ref const(Color) color = Color.white, BlendMode blendMode = BlendMode.Disabled ) fillFrustum;


Functions in structs is common, default args are often convenient:

struct MFMaterialInterface
{
extern (C) int       function(void* pPlatformData) registerMaterial;
extern (C) void      function() unregisterMaterial;

extern (C) void      function(MFMaterial* pMaterial, MFMaterialCreateParams *pCreateParams = null) createInstance;
extern (C) void      function(MFMaterial* pMaterial) destroyInstance;

extern (C) int       function() getNumParams;
extern (C) MFMaterialParameterInfo* function(int parameterIndex) getParameterInfo;
extern (C) void      function(MFMaterial* pMaterial, int parameterIndex, int argIndex, size_t value) setParameter;
extern (C) size_t    function(MFMaterial* pMaterial, int parameterIndex, int argIndex, void* pValue = null) getParameter;
}

extern (C) void function(const(char)* pName, const(MFMaterialInterface)* pInterface) MFMaterial_RegisterMaterialType;

This isn't the best demonstration of this pattern, just a compact one. But function pointers in structs/classes is not unusual.



Here's an advanced trick I use a lot since D doesn't extern to static C++ methods (heavily simplified, this is way out of context):

struct CPPClass
{
    this()
    {
        // not my actual code, but effectively, write 'this' and the C++ method pointer into a delegate on initialisation [I wrap this process up using magic]
        void** pDelegate = cast(void**)&cppNonVirtualMethod;
        pDelegate[0] = this;
        pDelegate[1] = pCPPMethodPointer;
    }

    void delegate(int x = 0) cppNonVirtualMethod; // C++ methods often have default args

private:
    // C++ method pointer received from foreign code during initialisation
    static void* pCPPMethodPointer;
}