Overloaded Methods#

C++ supports overloaded methods and functions. When you try to wrap an overloaded function the C++ compiler will throw an error message that says something like “no matching overloaded function found.”

For example, consider this C++ class:

class Container
{
public:
  size_t capacity()
  {
    return this->capacity_;
  }

  void capacity(size_t value)
  {
    this->capacity_ = value;
  }

private:
  size_t capacity_;
};

If you try and wrap the class like this you will get a compiler error:

Class c = define_class<Container>("Container")
 .define_constructor(Constructor<Container>())
 .define_method("capacity", &Container::capacity)
 .define_method("capacity=", &Container::capacity);

Instead, you need to tell the C++ compiler which overloaded method to use. There are several ways you can do this as explained below.

Template Parameter#

define_method is a template function, therefore one solution is to specify which method you are trying to call like this:

Class c = define_class<Container>("Container")
 .define_constructor(Constructor<Container>())
 .define_method<size_t(Container::*)()>("capacity", &Container::capacity)
 .define_method<void(Container::*)(size_t)>("capacity=", &Container::capacity);

size_t(Container::*)() and void(Container::*)(size_t) are C++ pointers to member functions.

Using#

Another solution is via C++ using functionality, like this:

using Getter_T = size_t(Container::*)();
using Setter_T = void(Container::*)(size_t);

Class c = define_class<Container>("Container")
  .define_constructor(Constructor<Container>())
  .define_method<Getter_T>("capacity", &Container::capacity)
  .define_method<Setter_T>("capacity=", &Container::capacity);

Or even like this:

using Getter_T = size_t(Container::*)();
using Setter_T = void(Container::*)(size_t);

Class c = define_class<Container>("Container")
  .define_constructor(Constructor<Container>())
  .define_method("capacity", (Getter_T)&Container::capacity)
  .define_method("capacity=", (Setter_T)&Container::capacity);

Typedef#

If you are old school, and like obtuse syntax, you can also use a typdef like this:

extern "C"
void Init_Container()
{
    typedef size_t(Container::* Getter_T)();
    typedef void (Container::* Setter_T)(size_t);

    Class c = define_class<Container>("Container")
      .define_constructor(Constructor<Container>())
      .define_method("capacity", (Getter_T)&Container::capacity)
      .define_method("capacity=", (Setter_T)&Container::capacity);
}

Ruby Example#

Once you have wrapped this class, it is easy to use in Ruby:

container = Container.new
container.capacity = 6
puts container.capacity

The printed result will be 7.