mirror of
https://github.com/pybind/pybind11.git
synced 2026-06-06 06:11:25 +00:00
Use stricter brace initialization
This updates the `py::init` constructors to only use brace initialization for aggregate initiailization if there is no constructor with the given arguments. This, in particular, fixes the regression in #1247 where the presence of a `std::initializer_list<T>` constructor started being invoked for constructor invocations in 2.2 even when there was a specific constructor of the desired type. The added test case demonstrates: without this change, it fails to compile because the `.def(py::init<std::vector<int>>())` constructor tries to invoke the `T(std::initializer_list<std::vector<int>>)` constructor rather than the `T(std::vector<int>)` constructor. By only using `new T{...}`-style construction when a `T(...)` constructor doesn't exist, we should bypass this by while still allowing `py::init<...>` to be used for aggregate type initialization (since such types, by definition, don't have a user-declared constructor).
This commit is contained in:
@@ -10,6 +10,16 @@
|
||||
#include "pybind11_tests.h"
|
||||
#include "constructor_stats.h"
|
||||
#include "local_bindings.h"
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
// test_brace_initialization
|
||||
struct NoBraceInitialization {
|
||||
NoBraceInitialization(std::vector<int> v) : vec{std::move(v)} {}
|
||||
template <typename T>
|
||||
NoBraceInitialization(std::initializer_list<T> l) : vec(l) {}
|
||||
|
||||
std::vector<int> vec;
|
||||
};
|
||||
|
||||
TEST_SUBMODULE(class_, m) {
|
||||
// test_instance
|
||||
@@ -299,6 +309,12 @@ TEST_SUBMODULE(class_, m) {
|
||||
.def(py::init<int, const std::string &>())
|
||||
.def_readwrite("field1", &BraceInitialization::field1)
|
||||
.def_readwrite("field2", &BraceInitialization::field2);
|
||||
// We *don't* want to construct using braces when the given constructor argument maps to a
|
||||
// constructor, because brace initialization could go to the wrong place (in particular when
|
||||
// there is also an `initializer_list<T>`-accept constructor):
|
||||
py::class_<NoBraceInitialization>(m, "NoBraceInitialization")
|
||||
.def(py::init<std::vector<int>>())
|
||||
.def_readonly("vec", &NoBraceInitialization::vec);
|
||||
|
||||
// test_reentrant_implicit_conversion_failure
|
||||
// #1035: issue with runaway reentrant implicit conversion
|
||||
|
||||
Reference in New Issue
Block a user