pybind11 icon indicating copy to clipboard operation
pybind11 copied to clipboard

[BUG]: PYBIND11_NUMPY_DTYPE doesn't support templated types with multiple template arguments

Open Bidski opened this issue 2 years ago • 2 comments

Required prerequisites

  • [X] Make sure you've read the documentation. Your issue may be addressed there.
  • [X] Search the issue tracker and Discussions to verify that this hasn't already been reported. +1 or comment there if it has.
  • [X] Consider asking first in the Gitter chat room or in a Discussion.

Problem description

Compiler errors are thrown when using PYBIND11_NUMPY_DTYPE with a struct with multiple template arguments. The errors are due to the comma in the template argument list causing the C++ preprocessor to expand the template arguments into extra macro arguments.

I am using pybind11 v2.9.2 and gcc 12.1

Reproducible example code

This code

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>

namespace py = pybind11;

template<typename T, typename U>
struct TestStruct {
    T a;
    int b;
    U c;
};

PYBIND11_MODULE(numpy_dtype_test, pymodule) {
    PYBIND11_NUMPY_DTYPE(TestStruct<float, double>, a, b, c);
}

Produces this error

pybind.cpp:14:5: error: wrong number of template arguments (1, should be 2)
   14 |     PYBIND11_NUMPY_DTYPE(TestStruct<float, double>, a, b, c);

Wrapping the first argument in parentheses doesn't help PYBIND11_NUMPY_DTYPE((TestStruct<float, double>), a, b, c);. This produces error: template argument 1 is invalid, I suspect because C++ doesn't like having the parentheses in the template argument (after the macro is expanded)

Using #define COMMA , and PYBIND11_NUMPY_DTYPE(TestStruct<float COMMA double>, a, b, c); fails with error: wrong number of template arguments (1, should be 2). This fails in a slightly different way to the first error. The first expansion of TestStruct<float COMMA double> works as desired, but subsequent expansion fail.

Using #define TEMPLATE_TYPE( ... ) __VA_ARGS__ and #define TEMPLATE_TYPE(A,B) A,B with PYBIND11_NUMPY_DTYPE(TEMPLATE_TYPE(TestStruct<float, double>), a, b, c); fail in similar way to #define COMMA , (but I think the point of failure is pushed slightly later in the macro expansion).

Bidski avatar Jun 20 '22 01:06 Bidski

@Bidski As a workaround, you can try to create an alias TestStruct<float, double> using the "using" keyword.

Skylion007 avatar Jun 29 '22 22:06 Skylion007

@Skylion007 you are correct, a using alias does create a viable workaround

Bidski avatar Jun 29 '22 23:06 Bidski