www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Static and non-static method overloading

reply Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
I have a question about static and non-static methods overloading.
I have this module:

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

/**
  * Dynamic library interfacing module.
  */
module dynlib;

public:
    /**
      * A lazily loaded cached dynamic library.
      */
    class DynLib
    {
    public:
        alias void* Symbol;

        /**
          * Loads or returns already loaded dynamic library.
          */
        static DynLib opIndex(in char[] name)
        {
            auto lib = name in _libraries;
            if(lib)
                return *lib;
            _libraries[name] = new DynLib(name);
            return DynLib[name];
        }

        /**
          * Loads or returns already loaded symbol from this dynamic
library.
          */
        Symbol opIndex(in char[] name)
        {
            auto sym = name in _symbols;
            if(sym)
                return *sym;
            version(Windows)
                _symbols[name] = GetProcAddress(_handle, name.toStringz);
            else version(Posix)
                _symbols[name] = dlsym(_handle, name.toStringz);
            return DynLib[name];
        }

        bool empty()  property
        {
            return _handle is null;
        }

    private:
        alias void* Handle;

        static DynLib[string] _libraries;
        static Symbol[string] _symbols;
        Handle _handle;

        this(in char[] name)
        {
            version(Windows)
                _handle = LoadLibraryA(name.toStringz);
            else version(Posix)
                _handle = dlopen(name.toStringz, RTLD_NOW);
        }

        ~this()
        {
            version(Windows)
                FreeLibrary(_handle);
            version(Posix)
                dlclose(_handle);
        }

        unittest
        {
            DynLib dl;
            version(Windows)
                dl = DynLib["OpenGL32.dll"];
            version(Posix)
                dl = DynLib["libGL.so"];
            assert(!dl.empty);

            DynLib.Symbol sym = dl["glClearColor"];
            assert(sym !is null);
        }
    }

private:
    import std.string: toStringz;

    version(Windows)
        import core.sys.windows.windows: LoadLibraryA, FreeLibrary,
GetProcAddress;
    else version(Posix)
        import core.sys.posix.dlfcn: dlopen, dlclose, dlsym;

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

And when i compile this, i get an unexpected error:

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

dynlib.d(24): Error: function dynlib.DynLib.opIndex called with argument
types:
        ((const(char[])))
matches both:
        dynlib.DynLib.opIndex(in const(char[]) name)
and:
        dynlib.DynLib.opIndex(in const(char[]) name)
dynlib.d(39): Error: function dynlib.DynLib.opIndex called with argument
types:
        ((const(char[])))
matches both:
        dynlib.DynLib.opIndex(in const(char[]) name)
and:
        dynlib.DynLib.opIndex(in const(char[]) name)
dynlib.d(39): Error: cannot implicitly convert expression (opIndex(name)) of
type dynlib.DynLib to void*

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

My point is: How can this be ambiguous, when i explicitly call the static
method from the class name, not the object and when i call a method from an
object, the most obvious choice is the non-static one?

Cheers,
Gor.
Sep 27 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/27/2011 05:11 PM, Gor Gyolchanyan wrote:
 I have a question about static and non-static methods overloading.
 I have this module:

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

 /**
    * Dynamic library interfacing module.
    */
 module dynlib;

 public:
      /**
        * A lazily loaded cached dynamic library.
        */
      class DynLib
      {
      public:
          alias void* Symbol;

          /**
            * Loads or returns already loaded dynamic library.
            */
          static DynLib opIndex(in char[] name)
          {
              auto lib = name in _libraries;
              if(lib)
                  return *lib;
              _libraries[name] = new DynLib(name);
              return DynLib[name];
          }

          /**
            * Loads or returns already loaded symbol from this dynamic
 library.
            */
          Symbol opIndex(in char[] name)
          {
              auto sym = name in _symbols;
              if(sym)
                  return *sym;
              version(Windows)
                  _symbols[name] = GetProcAddress(_handle, name.toStringz);
              else version(Posix)
                  _symbols[name] = dlsym(_handle, name.toStringz);
              return DynLib[name];
          }

          bool empty()  property
          {
              return _handle is null;
          }

      private:
          alias void* Handle;

          static DynLib[string] _libraries;
          static Symbol[string] _symbols;
          Handle _handle;

          this(in char[] name)
          {
              version(Windows)
                  _handle = LoadLibraryA(name.toStringz);
              else version(Posix)
                  _handle = dlopen(name.toStringz, RTLD_NOW);
          }

          ~this()
          {
              version(Windows)
                  FreeLibrary(_handle);
              version(Posix)
                  dlclose(_handle);
          }

          unittest
          {
              DynLib dl;
              version(Windows)
                  dl = DynLib["OpenGL32.dll"];
              version(Posix)
                  dl = DynLib["libGL.so"];
              assert(!dl.empty);

              DynLib.Symbol sym = dl["glClearColor"];
              assert(sym !is null);
          }
      }

 private:
      import std.string: toStringz;

      version(Windows)
          import core.sys.windows.windows: LoadLibraryA, FreeLibrary,
 GetProcAddress;
      else version(Posix)
          import core.sys.posix.dlfcn: dlopen, dlclose, dlsym;

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

 And when i compile this, i get an unexpected error:

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

 dynlib.d(24): Error: function dynlib.DynLib.opIndex called with argument
 types:
          ((const(char[])))
 matches both:
          dynlib.DynLib.opIndex(in const(char[]) name)
 and:
          dynlib.DynLib.opIndex(in const(char[]) name)
 dynlib.d(39): Error: function dynlib.DynLib.opIndex called with argument
 types:
          ((const(char[])))
 matches both:
          dynlib.DynLib.opIndex(in const(char[]) name)
 and:
          dynlib.DynLib.opIndex(in const(char[]) name)
 dynlib.d(39): Error: cannot implicitly convert expression
 (opIndex(name)) of type dynlib.DynLib to void*

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

 My point is: How can this be ambiguous, when i explicitly call the
 static method from the class name, not the object and when i call a
 method from an object, the most obvious choice is the non-static one?

 Cheers,
 Gor.
There as been some discussion about this issue and afaik Steve has filed a bug report. Currently, it is possible to call a static method on a class instance.
Sep 27 2011
parent reply Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
So, is there any plan to forbid calling static methods from class instance
or is the bug gonna just fix the ambiguity, while still allowing to call
static methods if no appropriate non-static one is available?

Cheers,
Gor.

On Tue, Sep 27, 2011 at 7:23 PM, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 09/27/2011 05:11 PM, Gor Gyolchanyan wrote:

 I have a question about static and non-static methods overloading.
 I have this module:

 ------------------------------**------------------------------**
 --------------------

 /**
   * Dynamic library interfacing module.
   */
 module dynlib;

 public:
     /**
       * A lazily loaded cached dynamic library.
       */
     class DynLib
     {
     public:
         alias void* Symbol;

         /**
           * Loads or returns already loaded dynamic library.
           */
         static DynLib opIndex(in char[] name)
         {
             auto lib = name in _libraries;
             if(lib)
                 return *lib;
             _libraries[name] = new DynLib(name);
             return DynLib[name];
         }

         /**
           * Loads or returns already loaded symbol from this dynamic
 library.
           */
         Symbol opIndex(in char[] name)
         {
             auto sym = name in _symbols;
             if(sym)
                 return *sym;
             version(Windows)
                 _symbols[name] = GetProcAddress(_handle, name.toStringz);
             else version(Posix)
                 _symbols[name] = dlsym(_handle, name.toStringz);
             return DynLib[name];
         }

         bool empty()  property
         {
             return _handle is null;
         }

     private:
         alias void* Handle;

         static DynLib[string] _libraries;
         static Symbol[string] _symbols;
         Handle _handle;

         this(in char[] name)
         {
             version(Windows)
                 _handle = LoadLibraryA(name.toStringz);
             else version(Posix)
                 _handle = dlopen(name.toStringz, RTLD_NOW);
         }

         ~this()
         {
             version(Windows)
                 FreeLibrary(_handle);
             version(Posix)
                 dlclose(_handle);
         }

         unittest
         {
             DynLib dl;
             version(Windows)
                 dl = DynLib["OpenGL32.dll"];
             version(Posix)
                 dl = DynLib["libGL.so"];
             assert(!dl.empty);

             DynLib.Symbol sym = dl["glClearColor"];
             assert(sym !is null);
         }
     }

 private:
     import std.string: toStringz;

     version(Windows)
         import core.sys.windows.windows: LoadLibraryA, FreeLibrary,
 GetProcAddress;
     else version(Posix)
         import core.sys.posix.dlfcn: dlopen, dlclose, dlsym;

 ------------------------------**------------------------------**
 --------------------

 And when i compile this, i get an unexpected error:

 ------------------------------**------------------------------**
 --------------------

 dynlib.d(24): Error: function dynlib.DynLib.opIndex called with argument
 types:
         ((const(char[])))
 matches both:
         dynlib.DynLib.opIndex(in const(char[]) name)
 and:
         dynlib.DynLib.opIndex(in const(char[]) name)
 dynlib.d(39): Error: function dynlib.DynLib.opIndex called with argument
 types:
         ((const(char[])))
 matches both:
         dynlib.DynLib.opIndex(in const(char[]) name)
 and:
         dynlib.DynLib.opIndex(in const(char[]) name)
 dynlib.d(39): Error: cannot implicitly convert expression
 (opIndex(name)) of type dynlib.DynLib to void*

 ------------------------------**------------------------------**
 --------------------

 My point is: How can this be ambiguous, when i explicitly call the
 static method from the class name, not the object and when i call a
 method from an object, the most obvious choice is the non-static one?

 Cheers,
 Gor.
There as been some discussion about this issue and afaik Steve has filed a bug report. Currently, it is possible to call a static method on a class instance.
Sep 27 2011
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 27 Sep 2011 11:38:40 -0400, Gor Gyolchanyan  
<gor.f.gyolchanyan gmail.com> wrote:

 So, is there any plan to forbid calling static methods from class  
 instance
 or is the bug gonna just fix the ambiguity, while still allowing to call
 static methods if no appropriate non-static one is available?
It's an enhancement request, no idea if it will make it in. Feel free to comment: http://d.puremagic.com/issues/show_bug.cgi?id=6579 -Steve
Sep 27 2011