[BUG]: Conditionally enabled member functions using concepts leads to compiler error
Open
Nobody has claimed this yet.
triage
- Dominant language
- C++
- Stars
- 18k
- Forks
- 2.3k
- Avg merge
- 5d 17h
- Merged PRs (30d)
- 10
Description
Required prerequisites
- Make sure you've read the documentation. Your issue may be addressed there.
- Search the issue tracker and Discussions to verify that this hasn't already been reported. +1 or comment there if it has.
- Consider asking first in the Gitter chat room or in a Discussion.
What version (or hash if on master) of pybind11 are you using?
2.10.4
Problem description
See code example below, which leads to the following compiler error:
foo.cpp: In function 'void pybind11_init_bug(pybind11::module_&)':
foo.cpp:26:13: error: no matching function for call to 'pybind11::class_<Foo<int> >::def(const char [4], <unresolved overloaded function type>)'
25 | py::class_<Foo<int>>(m, "FooInt")
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 | .def("foo", &Foo<int>::foo);
| ~~~~^~~~~~~~~~~~~~~~~~~~~~~
In file included from foo.cpp:2:
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1567:13: note: candidate: 'template<class Func, class ... Extra> pybind11::class_<type_, options>& pybind11::class_<type_, options>::def(const char*, Func&&, const Extra& ...) [with Func = Func; Extra = {Extra ...}; type_ = Foo<int>; options = {}]'
1567 | class_ &def(const char *name_, Func &&f, const Extra &...extra) {
| ^~~
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1567:13: note: template argument deduction/substitution failed:
foo.cpp:26:13: note: couldn't deduce template parameter 'Func'
25 | py::class_<Foo<int>>(m, "FooInt")
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 | .def("foo", &Foo<int>::foo);
| ~~~~^~~~~~~~~~~~~~~~~~~~~~~
In file included from foo.cpp:2:
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1592:13: note: candidate: 'template<class T, class ... Extra, typename std::enable_if<T::op_enable_if_hook, int>::type <anonymous> > pybind11::class_<type_, options>& pybind11::class_<type_, options>::def(const T&, const Extra& ...) [with T = T; Extra = {Extra ...}; typename std::enable_if<T::op_enable_if_hook, int>::type <anonymous> = <anonymous>; type_ = Foo<int>; options = {}]'
1592 | class_ &def(const T &op, const Extra &...extra) {
| ^~~
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1592:13: note: template argument deduction/substitution failed:
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1591:95: error: 'op_enable_if_hook' is not a member of 'char [4]'
1591 | template <typename T, typename... Extra, detail::enable_if_t<T::op_enable_if_hook, int> = 0>
| ^
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1604:13: note: candidate: 'template<class ... Args, class ... Extra> pybind11::class_<type_, options>& pybind11::class_<type_, options>::def(const pybind11::detail::initimpl::constructor<Args ...>&, const Extra& ...) [with Args = {Args ...}; Extra = {Extra ...}; type_ = Foo<int>; options = {}]'
1604 | class_ &def(const detail::initimpl::constructor<Args...> &init, const Extra &...extra) {
| ^~~
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1604:13: note: template argument deduction/substitution failed:
foo.cpp:26:13: note: mismatched types 'const pybind11::detail::initimpl::constructor<Args ...>' and 'const char [4]'
25 | py::class_<Foo<int>>(m, "FooInt")
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 | .def("foo", &Foo<int>::foo);
| ~~~~^~~~~~~~~~~~~~~~~~~~~~~
In file included from foo.cpp:2:
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1611:13: note: candidate: 'template<class ... Args, class ... Extra> pybind11::class_<type_, options>& pybind11::class_<type_, options>::def(const pybind11::detail::initimpl::alias_constructor<Args ...>&, const Extra& ...) [with Args = {Args ...}; Extra = {Extra ...}; type_ = Foo<int>; options = {}]'
1611 | class_ &def(const detail::initimpl::alias_constructor<Args...> &init, const Extra &...extra) {
| ^~~
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1611:13: note: template argument deduction/substitution failed:
foo.cpp:26:13: note: mismatched types 'const pybind11::detail::initimpl::alias_constructor<Args ...>' and 'const char [4]'
25 | py::class_<Foo<int>>(m, "FooInt")
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 | .def("foo", &Foo<int>::foo);
| ~~~~^~~~~~~~~~~~~~~~~~~~~~~
In file included from foo.cpp:2:
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1618:13: note: candidate: 'template<class ... Args, class ... Extra> pybind11::class_<type_, options>& pybind11::class_<type_, options>::def(pybind11::detail::initimpl::factory<Args ...>&&, const Extra& ...) [with Args = {Args ...}; Extra = {Extra ...}; type_ = Foo<int>; options = {}]'
1618 | class_ &def(detail::initimpl::factory<Args...> &&init, const Extra &...extra) {
| ^~~
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1618:13: note: template argument deduction/substitution failed:
foo.cpp:26:13: note: mismatched types 'pybind11::detail::initimpl::factory<Args ...>' and 'const char [4]'
25 | py::class_<Foo<int>>(m, "FooInt")
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 | .def("foo", &Foo<int>::foo);
| ~~~~^~~~~~~~~~~~~~~~~~~~~~~
In file included from foo.cpp:2:
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1624:13: note: candidate: 'template<class ... Args, class ... Extra> pybind11::class_<type_, options>& pybind11::class_<type_, options>::def(pybind11::detail::initimpl::pickle_factory<Args ...>&&, const Extra& ...) [with Args = {Args ...}; Extra = {Extra ...}; type_ = Foo<int>; options = {}]'
1624 | class_ &def(detail::initimpl::pickle_factory<Args...> &&pf, const Extra &...extra) {
| ^~~
C:/xxx/.conda/envs/p311/Lib/site-packages/pybind11/include/pybind11/pybind11.h:1624:13: note: template argument deduction/substitution failed:
foo.cpp:26:13: note: mismatched types 'pybind11::detail::initimpl::pickle_factory<Args ...>' and 'const char [4]'
25 | py::class_<Foo<int>>(m, "FooInt")
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 | .def("foo", &Foo<int>::foo);
| ~~~~^~~~~~~~~~~~~~~~~~~~~~~
ninja: build stopped: subcommand failed.
Reproducible example code
// foo.cpp
#include <iostream>
#include <pybind11/pybind11.h>
template <typename T>
struct Foo
{
// foo() takes no parameters if T == int
void foo() requires std::is_same_v<T, int>
{
std::cout << "int" << std::endl;
}
// foo() takes one parameter if T == double
void foo(double d) requires std::is_same_v<T, double>
{
std::cout << "double" << std::endl;
}
};
namespace py = pybind11;
PYBIND11_MODULE(bug, m)
{
py::class_<Foo<int>>(m, "FooInt")
.def("foo", &Foo<int>::foo); // <-- compiler error
}
Is this a regression? Put the last known working version here if it is.
Not a regression
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the foo.cpp reproducer and the pybind11.h class_::def overloads shown in the compiler output. Investigate how the constrained C++ member-function overloads are handled, then verify that the Foo binding compiles and preserves the intended foo() interface.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- backend-api-design
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100