Skip to content

Latest commit

 

History

History
86 lines (61 loc) · 4.22 KB

ConstOverloadRenameTransformation.md

File metadata and controls

86 lines (61 loc) · 4.22 KB

ConstOverloadRenameTransformation

[Transformation Source]

C# has no concept similar to C++'s const overloading. As such, methods which only differ by const-ness will be considered duplicates and result in a CS0111 error.

To work around this issue, this transformation will rename conflicting const overloads and hide them from Intellisense.

When this transformation is applicable

This transformation should generally always be used unless you have developed your own strategy for handling const overloads in your library.

You might also consider temporarily disabling this transformation to quickly identify where your native library uses const overloads so you can make a decision about whether or not you need to develop a more sophisticated workaround.

C++ background

C++ has a concept of const methods, they are methods which cannot modify the state of this. (Making them somewhat similar to readonly struct instance methods in C#.)

In C++ the a reference to a instance can be const or non-const. As such, sometimes it might make sense that a method would be const or non-const based on the type of reference you used to call it. To support this, C++ supports const overloading, where a developer can specify a different implementation depending on whether the reference was const.

Unfortunately const overloading doesn't translate well to C#. (Or const correctness in general for that matter, see #104.)

Note that this transformation hides the const overload from Intellisense because generally speaking, the implementation behind a const and non-const overload are identical. The const overload just gives the C++ compiler an implementation to use for const references. (In fact, if your library makes heavy use of const overloads you might consider just removing them entirely.)

Details

Given the following class in C++:

class HasConstOverloads
{
public:
    int& GetNumberReference();
    const int& GetNumberReference() const;
};

Biohazrd's translation stage will output the following declaration tree:

TranslatedRecord HasConstOverloads
    TranslatedFunction GetNumberReference
    TranslatedFunction GetNumberReference (IsConst) ☣

As you can see, there's two methods named GetNumberReference (as to be expected.)

This transformation renames the one marked with a ☣ and hides it from Intellisense:

TranslatedRecord HasConstOverloads
    TranslatedFunction GetNumberReference
    TranslatedFunction GetNumberReference_Const (IsConst) ☣

The resulting C# looks like the following. The lines marked with ☣ were affected by this transformation.

// This file was automatically generated by Biohazrd and should not be modified by hand!
using System.ComponentModel;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit, Size = 1)]
public unsafe partial struct HasConstOverloads
{
    [DllImport("Example.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?GetNumberReference@HasConstOverloads@@QEAAAEAHXZ", ExactSpelling = true)]
    private static extern int* GetNumberReference_PInvoke(HasConstOverloads* @this);

    public unsafe int* GetNumberReference()
    {
        fixed (HasConstOverloads* @this = &this)
        { return GetNumberReference_PInvoke(@this); }
    }

    [DllImport("Example.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?GetNumberReference@HasConstOverloads@@QEBAAEBHXZ", ExactSpelling = true)]
    private static extern int* GetNumberReference_Const_PInvoke(HasConstOverloads* @this);

    [EditorBrowsable(EditorBrowsableState.Never)] // ☣
    public unsafe int* GetNumberReference_Const() // ☣
    {
        fixed (HasConstOverloads* @this = &this)
        { return GetNumberReference_Const_PInvoke(@this); }
    }
}