pybind11
pybind11 copied to clipboard
[BUG]: PYBIND11_NUMPY_DTYPE doesn't support templated types with multiple template arguments
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 As a workaround, you can try to create an alias TestStruct<float, double> using the "using" keyword.
@Skylion007 you are correct, a using alias does create a viable workaround