alec.tu
alec.tu

Reputation: 1757

Unable to bind overloaded static member functions in pybind11

I tried to bind the static overloaded functions with pybind11, but got some problems.

Here is the sample code

#include <pybind11/pybind11.h>

namespace py = pybind11;

class TESTDB {
  public:
    static void aaaa(int a, int b) {printf("aaaaa");};
    static void aaaa(int a) {printf("xxxxx");};
};

PYBIND11_MODULE(example, m) {


  py::class_<TESTDB>(m, "db")
     .def_static("aaaa", (void (TESTDB::*)(int, int)) &TESTDB::aaaa);

}

but it's failed to compile due to

error: no matches converting function ‘aaaa’ to type ‘void (class TESTDB::*)(int, int)’
   .def_static("aaaa", (void (TESTDB::*)(int, int)) &TESTDB::aaaa);
 note: candidates are: static void TESTDB::aaaa(int)
 static void aaaa(int a) {printf("xxxxx");};
 note:                 static void TESTDB::aaaa(int, int)
 static void aaaa(int a, int b) {printf("aaaaa");};

any idea?

thank you

Upvotes: 3

Views: 2969

Answers (2)

Hiroki
Hiroki

Reputation: 2880

Just FYI - First, 8.3.1 Pointers [dcl.ptr] / 1 of the C++ standard draft n3337 (essentially C++11) states

In a declaration T D where D has the form

* attribute-specifier-seq cv-qualifier-seq D1

and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T,” then the type of the identifier of D is “derived-declarator-type-list cv-qualifier-seq pointer to T.” ...

and 8.3.3 Pointers to members [dcl.mptr] / 1 states

In a declaration T D where D has the form

nested-name-specifier * attribute-specifier-seq cv-qualifier-seq D1

and the nested-name-specifier denotes a class, and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T”, then the type of the identifier of D is “derived-declarator-type-list cv-qualifier-seq pointer to member of class nested-name-specifier of type T”. ...

These statements mean that we have to use the above nested-name-specifier TESTDB:: in TESTDB::* if and only if the function TESTDB::aaaa is a member function.

Next, 5.2.2 Function call [expr.call] states

  1. There are two kinds of function call: ordinary function call and member function63 (9.3) call. ...

where the footnote 63 is

63) A static member function (9.4) is an ordinary function.

This implies that your static member function TESTDB::aaaa is an ordinary function, not a member function. Thus you must not specify TESTDB:: in the current cast.


In summary, you have to disambiguate the two overloads of TESTDB::aaaa like this:

Live DEMO

static_cast<void (*)(int, int)>(&TESTDB::aaaa)

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409136

The problem is your cast (void (TESTDB::*)(int, int)). That cast is casting the pointer to the static member function into a pointer to non-static member function, which is incorrect.

Since the functions are static, you should simply cast them as pointers to ordinary non-member functions:

py::class_<TESTDB>(m, "db")
    .def_static("aaaa", static_cast<void (*)(int, int)>(&TESTDB::aaaa));

Upvotes: 7

Related Questions