Merge branch 'master' into sh_merge_master

This commit is contained in:
Ralf W. Grosse-Kunstleve
2021-09-08 18:56:35 -07:00
43 changed files with 295 additions and 148 deletions

View File

@@ -6,7 +6,7 @@
/// Simple class used to test py::local:
template <int> class LocalBase {
public:
LocalBase(int i) : i(i) { }
explicit LocalBase(int i) : i(i) { }
int i = -1;
};
@@ -75,11 +75,11 @@ py::class_<T> bind_local(Args && ...args) {
namespace pets {
class Pet {
public:
Pet(std::string name) : name_(std::move(name)) {}
explicit Pet(std::string name) : name_(std::move(name)) {}
std::string name_;
const std::string &name() const { return name_; }
};
} // namespace pets
struct MixGL { int i; MixGL(int i) : i{i} {} };
struct MixGL2 { int i; MixGL2(int i) : i{i} {} };
struct MixGL { int i; explicit MixGL(int i) : i{i} {} };
struct MixGL2 { int i; explicit MixGL2(int i) : i{i} {} };

View File

@@ -65,7 +65,7 @@ public:
ref() : m_ptr(nullptr) { print_default_created(this); track_default_created((ref_tag*) this); }
/// Construct a reference from a pointer
ref(T *ptr) : m_ptr(ptr) {
explicit ref(T *ptr) : m_ptr(ptr) {
if (m_ptr) ((Object *) m_ptr)->incRef();
print_created(this, "from pointer", m_ptr); track_created((ref_tag*) this, "from pointer");
@@ -165,7 +165,7 @@ public:
const T& operator*() const { return *m_ptr; }
/// Return a pointer to the referenced object
operator T* () { return m_ptr; }
explicit operator T* () { return m_ptr; }
/// Return a const pointer to the referenced object
T* get_ptr() { return m_ptr; }

View File

@@ -123,7 +123,7 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
class Dog : public pets::Pet {
public:
Dog(std::string name) : Pet(std::move(name)) {}
explicit Dog(std::string name) : Pet(std::move(name)) {}
};
py::class_<pets::Pet>(m, "Pet", py::module_local())
.def("name", &pets::Pet::name);

View File

@@ -1,9 +1,6 @@
#pragma once
// This must be kept first for MSVC 2015.
// Do not remove the empty line between the #includes.
#include <pybind11/pybind11.h>
#include <pybind11/eval.h>
#if defined(_MSC_VER) && _MSC_VER < 1910
@@ -19,7 +16,7 @@ class test_initializer {
using Initializer = void (*)(py::module_ &);
public:
test_initializer(Initializer init);
explicit test_initializer(Initializer init);
test_initializer(const char *submodule_name, Initializer init);
};
@@ -35,7 +32,7 @@ struct UnregisteredType { };
class UserType {
public:
UserType() = default;
UserType(int i) : i(i) { }
explicit UserType(int i) : i(i) { }
int value() const { return i; }
void set(int set) { i = set; }

View File

@@ -122,7 +122,7 @@ TEST_SUBMODULE(buffers, m) {
// test_inherited_protocol
class SquareMatrix : public Matrix {
public:
SquareMatrix(py::ssize_t n) : Matrix(n, n) { }
explicit SquareMatrix(py::ssize_t n) : Matrix(n, n) {}
};
// Derived classes inherit the buffer protocol and the buffer access function
py::class_<SquareMatrix, Matrix>(m, "SquareMatrix")
@@ -173,7 +173,7 @@ TEST_SUBMODULE(buffers, m) {
struct BufferReadOnly {
const uint8_t value = 0;
BufferReadOnly(uint8_t value): value(value) {}
explicit BufferReadOnly(uint8_t value) : value(value) {}
py::buffer_info get_buffer_info() {
return py::buffer_info(&value, 1);

View File

@@ -25,16 +25,28 @@ class type_caster<ConstRefCasted> {
// cast operator.
bool load(handle, bool) { return true; }
operator ConstRefCasted &&() {
explicit operator ConstRefCasted &&() {
value = {1};
// NOLINTNEXTLINE(performance-move-const-arg)
return std::move(value);
}
operator ConstRefCasted&() { value = {2}; return value; }
operator ConstRefCasted*() { value = {3}; return &value; }
explicit operator ConstRefCasted &() {
value = {2};
return value;
}
explicit operator ConstRefCasted *() {
value = {3};
return &value;
}
operator const ConstRefCasted&() { value = {4}; return value; }
operator const ConstRefCasted*() { value = {5}; return &value; }
explicit operator const ConstRefCasted &() {
value = {4};
return value;
}
explicit operator const ConstRefCasted *() {
value = {5};
return &value;
}
// custom cast_op to explicitly propagate types to the conversion operators.
template <typename T_>

View File

@@ -81,16 +81,55 @@ TEST_SUBMODULE(callbacks, m) {
};
// Export the payload constructor statistics for testing purposes:
m.def("payload_cstats", &ConstructorStats::get<Payload>);
/* Test cleanup of lambda closure */
m.def("test_cleanup", []() -> std::function<void()> {
m.def("test_lambda_closure_cleanup", []() -> std::function<void()> {
Payload p;
// In this situation, `Func` in the implementation of
// `cpp_function::initialize` is NOT trivially destructible.
return [p]() {
/* p should be cleaned up when the returned function is garbage collected */
(void) p;
};
});
class CppCallable {
public:
CppCallable() { track_default_created(this); }
~CppCallable() { track_destroyed(this); }
CppCallable(const CppCallable &) { track_copy_created(this); }
CppCallable(CppCallable &&) noexcept { track_move_created(this); }
void operator()() {}
};
m.def("test_cpp_callable_cleanup", []() {
// Related issue: https://github.com/pybind/pybind11/issues/3228
// Related PR: https://github.com/pybind/pybind11/pull/3229
py::list alive_counts;
ConstructorStats &stat = ConstructorStats::get<CppCallable>();
alive_counts.append(stat.alive());
{
CppCallable cpp_callable;
alive_counts.append(stat.alive());
{
// In this situation, `Func` in the implementation of
// `cpp_function::initialize` IS trivially destructible,
// only `capture` is not.
py::cpp_function py_func(cpp_callable);
py::detail::silence_unused_warnings(py_func);
alive_counts.append(stat.alive());
}
alive_counts.append(stat.alive());
{
py::cpp_function py_func(std::move(cpp_callable));
py::detail::silence_unused_warnings(py_func);
alive_counts.append(stat.alive());
}
alive_counts.append(stat.alive());
}
alive_counts.append(stat.alive());
return alive_counts;
});
// test_cpp_function_roundtrip
/* Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer */
m.def("dummy_function", &dummy_function);

View File

@@ -79,13 +79,18 @@ def test_keyword_args_and_generalized_unpacking():
def test_lambda_closure_cleanup():
m.test_cleanup()
m.test_lambda_closure_cleanup()
cstats = m.payload_cstats()
assert cstats.alive() == 0
assert cstats.copy_constructions == 1
assert cstats.move_constructions >= 1
def test_cpp_callable_cleanup():
alive_counts = m.test_cpp_callable_cleanup()
assert alive_counts == [0, 1, 2, 1, 2, 1, 0]
def test_cpp_function_roundtrip():
"""Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer"""

View File

@@ -29,7 +29,7 @@ namespace {
// test_brace_initialization
struct NoBraceInitialization {
NoBraceInitialization(std::vector<int> v) : vec{std::move(v)} {}
explicit NoBraceInitialization(std::vector<int> v) : vec{std::move(v)} {}
template <typename T>
NoBraceInitialization(std::initializer_list<T> l) : vec(l) {}
@@ -84,18 +84,18 @@ TEST_SUBMODULE(class_, m) {
class Dog : public Pet {
public:
Dog(const std::string &name) : Pet(name, "dog") {}
explicit Dog(const std::string &name) : Pet(name, "dog") {}
std::string bark() const { return "Woof!"; }
};
class Rabbit : public Pet {
public:
Rabbit(const std::string &name) : Pet(name, "parrot") {}
explicit Rabbit(const std::string &name) : Pet(name, "parrot") {}
};
class Hamster : public Pet {
public:
Hamster(const std::string &name) : Pet(name, "rodent") {}
explicit Hamster(const std::string &name) : Pet(name, "rodent") {}
};
class Chimera : public Pet {
@@ -222,7 +222,7 @@ TEST_SUBMODULE(class_, m) {
struct ConvertibleFromUserType {
int i;
ConvertibleFromUserType(UserType u) : i(u.value()) { }
explicit ConvertibleFromUserType(UserType u) : i(u.value()) {}
};
py::class_<ConvertibleFromUserType>(m, "AcceptsUserType")
@@ -277,7 +277,7 @@ TEST_SUBMODULE(class_, m) {
};
struct PyAliasedHasOpNewDelSize : AliasedHasOpNewDelSize {
PyAliasedHasOpNewDelSize() = default;
PyAliasedHasOpNewDelSize(int) { }
explicit PyAliasedHasOpNewDelSize(int) {}
std::uint64_t j;
};
struct HasOpNewDelBoth {

View File

@@ -37,7 +37,7 @@ template <> lacking_move_ctor empty<lacking_move_ctor>::instance_ = {};
class MoveOnlyInt {
public:
MoveOnlyInt() { print_default_created(this); }
MoveOnlyInt(int v) : value{v} { print_created(this, value); }
explicit MoveOnlyInt(int v) : value{v} { print_created(this, value); }
MoveOnlyInt(MoveOnlyInt &&m) noexcept {
print_move_created(this, m.value);
std::swap(value, m.value);
@@ -56,7 +56,7 @@ public:
class MoveOrCopyInt {
public:
MoveOrCopyInt() { print_default_created(this); }
MoveOrCopyInt(int v) : value{v} { print_created(this, value); }
explicit MoveOrCopyInt(int v) : value{v} { print_created(this, value); }
MoveOrCopyInt(MoveOrCopyInt &&m) noexcept {
print_move_created(this, m.value);
std::swap(value, m.value);
@@ -75,7 +75,7 @@ public:
class CopyOnlyInt {
public:
CopyOnlyInt() { print_default_created(this); }
CopyOnlyInt(int v) : value{v} { print_created(this, value); }
explicit CopyOnlyInt(int v) : value{v} { print_created(this, value); }
CopyOnlyInt(const CopyOnlyInt &c) { print_copy_created(this, c.value); value = c.value; }
CopyOnlyInt &operator=(const CopyOnlyInt &c) { print_copy_assigned(this, c.value); value = c.value; return *this; }
~CopyOnlyInt() { print_destroyed(this); }
@@ -107,8 +107,8 @@ public:
if (!src) return none().release();
return cast(*src, policy, parent);
}
operator CopyOnlyInt*() { return &value; }
operator CopyOnlyInt&() { return value; }
explicit operator CopyOnlyInt *() { return &value; }
explicit operator CopyOnlyInt &() { return value; }
template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>;
};
PYBIND11_NAMESPACE_END(detail)
@@ -219,7 +219,7 @@ TEST_SUBMODULE(copy_move_policies, m) {
// #389: rvp::move should fall-through to copy on non-movable objects
struct MoveIssue1 {
int v;
MoveIssue1(int v) : v{v} {}
explicit MoveIssue1(int v) : v{v} {}
MoveIssue1(const MoveIssue1 &c) = default;
MoveIssue1(MoveIssue1 &&) = delete;
};
@@ -227,7 +227,7 @@ TEST_SUBMODULE(copy_move_policies, m) {
struct MoveIssue2 {
int v;
MoveIssue2(int v) : v{v} {}
explicit MoveIssue2(int v) : v{v} {}
MoveIssue2(MoveIssue2 &&) = default;
};
py::class_<MoveIssue2>(m, "MoveIssue2").def(py::init<int>()).def_readwrite("value", &MoveIssue2::v);

View File

@@ -9,7 +9,7 @@ namespace py = pybind11;
PYBIND11_MODULE(external_module, m) {
class A {
public:
A(int value) : v{value} {};
explicit A(int value) : v{value} {};
int v;
};

View File

@@ -18,7 +18,7 @@ using namespace py::literals;
class Widget {
public:
Widget(std::string message) : message(std::move(message)) {}
explicit Widget(std::string message) : message(std::move(message)) {}
virtual ~Widget() = default;
std::string the_message() const { return message; }

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import pytest
import env
from pybind11_tests import enums as m
@@ -238,20 +239,26 @@ def test_duplicate_enum_name():
def test_char_underlying_enum(): # Issue #1331/PR #1334:
assert type(m.ScopedCharEnum.Positive.__int__()) is int
assert int(m.ScopedChar16Enum.Zero) == 0 # int() call should successfully return
assert int(m.ScopedChar16Enum.Zero) == 0
assert hash(m.ScopedChar32Enum.Positive) == 1
assert m.ScopedCharEnum.Positive.__getstate__() == 1 # return type is long in py2.x
if env.PY2:
assert m.ScopedCharEnum.Positive.__getstate__() == 1 # long
else:
assert type(m.ScopedCharEnum.Positive.__getstate__()) is int
assert m.ScopedWCharEnum(1) == m.ScopedWCharEnum.Positive
with pytest.raises(TypeError):
# Enum should construct with a int, even with char underlying type
m.ScopedWCharEnum("0")
# Even if the underlying type is char, only an int can be used to construct the enum:
m.ScopedCharEnum("0")
def test_bool_underlying_enum():
assert type(m.ScopedBoolEnum.TRUE.__int__()) is int
assert int(m.ScopedBoolEnum.FALSE) == 0
assert hash(m.ScopedBoolEnum.TRUE) == 1
assert m.ScopedBoolEnum.TRUE.__getstate__() == 1
if env.PY2:
assert m.ScopedBoolEnum.TRUE.__getstate__() == 1 # long
else:
assert type(m.ScopedBoolEnum.TRUE.__getstate__()) is int
assert m.ScopedBoolEnum(1) == m.ScopedBoolEnum.TRUE
# Enum could construct with a bool
# (bool is a strict subclass of int, and False will be converted to 0)

View File

@@ -81,7 +81,7 @@ private:
struct PythonCallInDestructor {
PythonCallInDestructor(const py::dict &d) : d(d) {}
explicit PythonCallInDestructor(const py::dict &d) : d(d) {}
~PythonCallInDestructor() { d["good"] = true; }
py::dict d;
@@ -90,7 +90,7 @@ struct PythonCallInDestructor {
struct PythonAlreadySetInDestructor {
PythonAlreadySetInDestructor(const py::str &s) : s(s) {}
explicit PythonAlreadySetInDestructor(const py::str &s) : s(s) {}
~PythonAlreadySetInDestructor() {
py::dict foo;
try {

View File

@@ -19,8 +19,9 @@
class TestFactory1 {
friend class TestFactoryHelper;
TestFactory1() : value("(empty)") { print_default_created(this); }
TestFactory1(int v) : value(std::to_string(v)) { print_created(this, value); }
TestFactory1(std::string v) : value(std::move(v)) { print_created(this, value); }
explicit TestFactory1(int v) : value(std::to_string(v)) { print_created(this, value); }
explicit TestFactory1(std::string v) : value(std::move(v)) { print_created(this, value); }
public:
std::string value;
TestFactory1(TestFactory1 &&) = delete;
@@ -33,8 +34,9 @@ public:
class TestFactory2 {
friend class TestFactoryHelper;
TestFactory2() : value("(empty2)") { print_default_created(this); }
TestFactory2(int v) : value(std::to_string(v)) { print_created(this, value); }
TestFactory2(std::string v) : value(std::move(v)) { print_created(this, value); }
explicit TestFactory2(int v) : value(std::to_string(v)) { print_created(this, value); }
explicit TestFactory2(std::string v) : value(std::move(v)) { print_created(this, value); }
public:
TestFactory2(TestFactory2 &&m) noexcept {
value = std::move(m.value);
@@ -53,9 +55,10 @@ class TestFactory3 {
protected:
friend class TestFactoryHelper;
TestFactory3() : value("(empty3)") { print_default_created(this); }
TestFactory3(int v) : value(std::to_string(v)) { print_created(this, value); }
explicit TestFactory3(int v) : value(std::to_string(v)) { print_created(this, value); }
public:
TestFactory3(std::string v) : value(std::move(v)) { print_created(this, value); }
explicit TestFactory3(std::string v) : value(std::move(v)) { print_created(this, value); }
TestFactory3(TestFactory3 &&m) noexcept {
value = std::move(m.value);
print_move_created(this);
@@ -72,13 +75,13 @@ public:
class TestFactory4 : public TestFactory3 {
public:
TestFactory4() : TestFactory3() { print_default_created(this); }
TestFactory4(int v) : TestFactory3(v) { print_created(this, v); }
explicit TestFactory4(int v) : TestFactory3(v) { print_created(this, v); }
~TestFactory4() override { print_destroyed(this); }
};
// Another class for an invalid downcast test
class TestFactory5 : public TestFactory3 {
public:
TestFactory5(int i) : TestFactory3(i) { print_created(this, i); }
explicit TestFactory5(int i) : TestFactory3(i) { print_created(this, i); }
~TestFactory5() override { print_destroyed(this); }
};
@@ -87,7 +90,7 @@ protected:
int value;
bool alias = false;
public:
TestFactory6(int i) : value{i} { print_created(this, i); }
explicit TestFactory6(int i) : value{i} { print_created(this, i); }
TestFactory6(TestFactory6 &&f) noexcept {
print_move_created(this);
value = f.value;
@@ -102,11 +105,20 @@ class PyTF6 : public TestFactory6 {
public:
// Special constructor that allows the factory to construct a PyTF6 from a TestFactory6 only
// when an alias is needed:
PyTF6(TestFactory6 &&base) : TestFactory6(std::move(base)) { alias = true; print_created(this, "move", value); }
PyTF6(int i) : TestFactory6(i) { alias = true; print_created(this, i); }
explicit PyTF6(TestFactory6 &&base) : TestFactory6(std::move(base)) {
alias = true;
print_created(this, "move", value);
}
explicit PyTF6(int i) : TestFactory6(i) {
alias = true;
print_created(this, i);
}
PyTF6(PyTF6 &&f) noexcept : TestFactory6(std::move(f)) { print_move_created(this); }
PyTF6(const PyTF6 &f) : TestFactory6(f) { print_copy_created(this); }
PyTF6(std::string s) : TestFactory6((int) s.size()) { alias = true; print_created(this, s); }
explicit PyTF6(std::string s) : TestFactory6((int) s.size()) {
alias = true;
print_created(this, s);
}
~PyTF6() override { print_destroyed(this); }
int get() override { PYBIND11_OVERRIDE(int, TestFactory6, get, /*no args*/); }
};
@@ -116,7 +128,7 @@ protected:
int value;
bool alias = false;
public:
TestFactory7(int i) : value{i} { print_created(this, i); }
explicit TestFactory7(int i) : value{i} { print_created(this, i); }
TestFactory7(TestFactory7 &&f) noexcept {
print_move_created(this);
value = f.value;
@@ -129,7 +141,10 @@ public:
};
class PyTF7 : public TestFactory7 {
public:
PyTF7(int i) : TestFactory7(i) { alias = true; print_created(this, i); }
explicit PyTF7(int i) : TestFactory7(i) {
alias = true;
print_created(this, i);
}
PyTF7(PyTF7 &&f) noexcept : TestFactory7(std::move(f)) { print_move_created(this); }
PyTF7(const PyTF7 &f) : TestFactory7(f) { print_copy_created(this); }
~PyTF7() override { print_destroyed(this); }
@@ -300,7 +315,7 @@ TEST_SUBMODULE(factory_constructors, m) {
// Class with a custom new operator but *without* a placement new operator (issue #948)
class NoPlacementNew {
public:
NoPlacementNew(int i) : i(i) { }
explicit NoPlacementNew(int i) : i(i) {}
static void *operator new(std::size_t s) {
auto *p = ::operator new(s);
py::print("operator new called, returning", reinterpret_cast<uintptr_t>(p));
@@ -324,8 +339,8 @@ TEST_SUBMODULE(factory_constructors, m) {
// Class that has verbose operator_new/operator_delete calls
struct NoisyAlloc {
NoisyAlloc(const NoisyAlloc &) = default;
NoisyAlloc(int i) { py::print(py::str("NoisyAlloc(int {})").format(i)); }
NoisyAlloc(double d) { py::print(py::str("NoisyAlloc(double {})").format(d)); }
explicit NoisyAlloc(int i) { py::print(py::str("NoisyAlloc(int {})").format(i)); }
explicit NoisyAlloc(double d) { py::print(py::str("NoisyAlloc(double {})").format(d)); }
~NoisyAlloc() { py::print("~NoisyAlloc()"); }
static void *operator new(size_t s) { py::print("noisy new"); return ::operator new(s); }

View File

@@ -91,7 +91,7 @@ TEST_SUBMODULE(local_bindings, m) {
class Cat : public pets::Pet {
public:
Cat(std::string name) : Pet(std::move(name)) {}
explicit Cat(std::string name) : Pet(std::move(name)) {}
};
py::class_<pets::Pet>(m, "Pet", py::module_local())
.def("get_name", &pets::Pet::name);

View File

@@ -19,9 +19,9 @@ using overload_cast_ = pybind11::detail::overload_cast_impl<Args...>;
class ExampleMandA {
public:
ExampleMandA() { print_default_created(this); }
ExampleMandA(int value) : value(value) { print_created(this, value); }
explicit ExampleMandA(int value) : value(value) { print_created(this, value); }
ExampleMandA(const ExampleMandA &e) : value(e.value) { print_copy_created(this); }
ExampleMandA(std::string&&) {}
explicit ExampleMandA(std::string &&) {}
ExampleMandA(ExampleMandA &&e) noexcept : value(e.value) { print_move_created(this); }
~ExampleMandA() { print_destroyed(this); }
@@ -124,14 +124,14 @@ class NoneCastTester {
public:
int answer = -1;
NoneCastTester() = default;
NoneCastTester(int v) : answer(v) {}
explicit NoneCastTester(int v) : answer(v) {}
};
struct StrIssue {
int val = -1;
StrIssue() = default;
StrIssue(int i) : val{i} {}
explicit StrIssue(int i) : val{i} {}
};
// Issues #854, #910: incompatible function args when member function/pointer is in unregistered base class

View File

@@ -20,7 +20,7 @@ TEST_SUBMODULE(modules, m) {
// test_reference_internal
class A {
public:
A(int v) : v(v) { print_created(this, v); }
explicit A(int v) : v(v) { print_created(this, v); }
~A() { print_destroyed(this); }
A(const A&) { print_copy_created(this); }
A& operator=(const A &copy) { print_copy_assigned(this); v = copy.v; return *this; }

View File

@@ -16,7 +16,7 @@ namespace {
// Many bases for testing that multiple inheritance from many classes (i.e. requiring extra
// space for holder constructed flags) works.
template <int N> struct BaseN {
BaseN(int i) : i(i) { }
explicit BaseN(int i) : i(i) {}
int i;
};
@@ -47,12 +47,12 @@ int VanillaStaticMix2::static_value = 12;
// test_multiple_inheritance_virtbase
struct Base1a {
Base1a(int i) : i(i) { }
explicit Base1a(int i) : i(i) {}
int foo() const { return i; }
int i;
};
struct Base2a {
Base2a(int i) : i(i) { }
explicit Base2a(int i) : i(i) {}
int bar() const { return i; }
int i;
};
@@ -77,7 +77,7 @@ TEST_SUBMODULE(multiple_inheritance, m) {
// test_multiple_inheritance_mix1
// test_multiple_inheritance_mix2
struct Base1 {
Base1(int i) : i(i) { }
explicit Base1(int i) : i(i) {}
int foo() const { return i; }
int i;
};
@@ -86,7 +86,7 @@ TEST_SUBMODULE(multiple_inheritance, m) {
.def("foo", &Base1::foo);
struct Base2 {
Base2(int i) : i(i) { }
explicit Base2(int i) : i(i) {}
int bar() const { return i; }
int i;
};

View File

@@ -52,7 +52,7 @@ TEST_SUBMODULE(numpy_vectorize, m) {
// Passthrough test: references and non-pod types should be automatically passed through (in the
// function definition below, only `b`, `d`, and `g` are vectorized):
struct NonPODClass {
NonPODClass(int v) : value{v} {}
explicit NonPODClass(int v) : value{v} {}
int value;
};
py::class_<NonPODClass>(m, "NonPODClass")
@@ -71,7 +71,7 @@ TEST_SUBMODULE(numpy_vectorize, m) {
// test_method_vectorization
struct VectorizeTestClass {
VectorizeTestClass(int v) : value{v} {};
explicit VectorizeTestClass(int v) : value{v} {};
float method(int x, float y) const { return y + (float) (x + value); }
int value = 0;
};

View File

@@ -67,7 +67,7 @@ TEST_SUBMODULE(pickling, m) {
// test_roundtrip
class Pickleable {
public:
Pickleable(const std::string &value) : m_value(value) { }
explicit Pickleable(const std::string &value) : m_value(value) { }
const std::string &value() const { return m_value; }
void setExtra1(int extra1) { m_extra1 = extra1; }
@@ -132,7 +132,7 @@ TEST_SUBMODULE(pickling, m) {
// test_roundtrip_with_dict
class PickleableWithDict {
public:
PickleableWithDict(const std::string &value) : value(value) { }
explicit PickleableWithDict(const std::string &value) : value(value) { }
std::string value;
int extra;

View File

@@ -20,7 +20,7 @@ template<typename T>
class NonZeroIterator {
const T* ptr_;
public:
NonZeroIterator(const T* ptr) : ptr_(ptr) {}
explicit NonZeroIterator(const T *ptr) : ptr_(ptr) {}
const T& operator*() const { return *ptr_; }
NonZeroIterator& operator++() { ++ptr_; return *this; }
};
@@ -77,9 +77,9 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
// test_sliceable
class Sliceable{
public:
Sliceable(int n): size(n) {}
int start,stop,step;
int size;
explicit Sliceable(int n) : size(n) {}
int start, stop, step;
int size;
};
py::class_<Sliceable>(m, "Sliceable")
.def(py::init<int>())
@@ -96,12 +96,12 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
// test_sequence
class Sequence {
public:
Sequence(size_t size) : m_size(size) {
explicit Sequence(size_t size) : m_size(size) {
print_created(this, "of size", m_size);
m_data = new float[size];
memset(m_data, 0, sizeof(float) * size);
}
Sequence(const std::vector<float> &value) : m_size(value.size()) {
explicit Sequence(const std::vector<float> &value) : m_size(value.size()) {
print_created(this, "of size", m_size, "from std::vector");
m_data = new float[m_size];
memcpy(m_data, &value[0], sizeof(float) * m_size);
@@ -239,7 +239,7 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
class StringMap {
public:
StringMap() = default;
StringMap(std::unordered_map<std::string, std::string> init)
explicit StringMap(std::unordered_map<std::string, std::string> init)
: map(std::move(init)) {}
void set(const std::string &key, std::string val) { map[key] = std::move(val); }
@@ -276,7 +276,7 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
// test_generalized_iterators
class IntPairs {
public:
IntPairs(std::vector<std::pair<int, int>> data) : data_(std::move(data)) {}
explicit IntPairs(std::vector<std::pair<int, int>> data) : data_(std::move(data)) {}
const std::pair<int, int>* begin() const { return data_.data(); }
private:
std::vector<std::pair<int, int>> data_;

View File

@@ -24,7 +24,7 @@ template <typename T> class huge_unique_ptr {
std::unique_ptr<T> ptr;
uint64_t padding[10];
public:
huge_unique_ptr(T *p) : ptr(p) {}
explicit huge_unique_ptr(T *p) : ptr(p) {}
T *get() { return ptr.get(); }
};
@@ -33,7 +33,7 @@ template <typename T>
class custom_unique_ptr {
std::unique_ptr<T> impl;
public:
custom_unique_ptr(T* p) : impl(p) { }
explicit custom_unique_ptr(T *p) : impl(p) {}
T* get() const { return impl.get(); }
T* release_ptr() { return impl.release(); }
};
@@ -46,7 +46,7 @@ class shared_ptr_with_addressof_operator {
std::shared_ptr<T> impl;
public:
shared_ptr_with_addressof_operator( ) = default;
shared_ptr_with_addressof_operator(T* p) : impl(p) { }
explicit shared_ptr_with_addressof_operator(T *p) : impl(p) {}
T* get() const { return impl.get(); }
T** operator&() { throw std::logic_error("Call of overloaded operator& is not expected"); }
};
@@ -59,7 +59,7 @@ class unique_ptr_with_addressof_operator {
std::unique_ptr<T> impl;
public:
unique_ptr_with_addressof_operator() = default;
unique_ptr_with_addressof_operator(T* p) : impl(p) { }
explicit unique_ptr_with_addressof_operator(T *p) : impl(p) {}
T* get() const { return impl.get(); }
T* release_ptr() { return impl.release(); }
T** operator&() { throw std::logic_error("Call of overloaded operator& is not expected"); }
@@ -68,7 +68,7 @@ public:
// Custom object with builtin reference counting (see 'object.h' for the implementation)
class MyObject1 : public Object {
public:
MyObject1(int value) : value(value) { print_created(this, toString()); }
explicit MyObject1(int value) : value(value) { print_created(this, toString()); }
std::string toString() const override { return "MyObject1[" + std::to_string(value) + "]"; }
protected:
~MyObject1() override { print_destroyed(this); }
@@ -80,7 +80,7 @@ private:
class MyObject2 {
public:
MyObject2(const MyObject2 &) = default;
MyObject2(int value) : value(value) { print_created(this, toString()); }
explicit MyObject2(int value) : value(value) { print_created(this, toString()); }
std::string toString() const { return "MyObject2[" + std::to_string(value) + "]"; }
virtual ~MyObject2() { print_destroyed(this); }
private:
@@ -91,7 +91,7 @@ private:
class MyObject3 : public std::enable_shared_from_this<MyObject3> {
public:
MyObject3(const MyObject3 &) = default;
MyObject3(int value) : value(value) { print_created(this, toString()); }
explicit MyObject3(int value) : value(value) { print_created(this, toString()); }
std::string toString() const { return "MyObject3[" + std::to_string(value) + "]"; }
virtual ~MyObject3() { print_destroyed(this); }
private:
@@ -104,7 +104,7 @@ class MyObject4;
std::unordered_set<MyObject4 *> myobject4_instances;
class MyObject4 {
public:
MyObject4(int value) : value{value} {
explicit MyObject4(int value) : value{value} {
print_created(this);
myobject4_instances.insert(this);
}
@@ -130,7 +130,7 @@ class MyObject4a;
std::unordered_set<MyObject4a *> myobject4a_instances;
class MyObject4a {
public:
MyObject4a(int i) {
explicit MyObject4a(int i) {
value = i;
print_created(this);
myobject4a_instances.insert(this);
@@ -153,14 +153,14 @@ protected:
// Object derived but with public destructor and no Deleter in default holder
class MyObject4b : public MyObject4a {
public:
MyObject4b(int i) : MyObject4a(i) { print_created(this); }
explicit MyObject4b(int i) : MyObject4a(i) { print_created(this); }
~MyObject4b() override { print_destroyed(this); }
};
// test_large_holder
class MyObject5 { // managed by huge_unique_ptr
public:
MyObject5(int value) : value{value} { print_created(this); }
explicit MyObject5(int value) : value{value} { print_created(this); }
~MyObject5() { print_destroyed(this); }
int value;
};
@@ -222,7 +222,7 @@ struct TypeForHolderWithAddressOf {
// test_move_only_holder_with_addressof_operator
struct TypeForMoveOnlyHolderWithAddressOf {
TypeForMoveOnlyHolderWithAddressOf(int value) : value{value} { print_created(this); }
explicit TypeForMoveOnlyHolderWithAddressOf(int value) : value{value} { print_created(this); }
~TypeForMoveOnlyHolderWithAddressOf() { print_destroyed(this); }
std::string toString() const {
return "MoveOnlyHolderWithAddressOf[" + std::to_string(value) + "]";
@@ -242,7 +242,7 @@ struct ElementBase {
};
struct ElementA : ElementBase {
ElementA(int v) : v(v) { }
explicit ElementA(int v) : v(v) {}
int value() const { return v; }
int v;
};
@@ -323,9 +323,9 @@ TEST_SUBMODULE(smart_ptr, m) {
py::implicitly_convertible<py::int_, MyObject1>();
m.def("make_object_1", []() -> Object * { return new MyObject1(1); });
m.def("make_object_2", []() -> ref<Object> { return new MyObject1(2); });
m.def("make_object_2", []() -> ref<Object> { return ref<Object>(new MyObject1(2)); });
m.def("make_myobject1_1", []() -> MyObject1 * { return new MyObject1(4); });
m.def("make_myobject1_2", []() -> ref<MyObject1> { return new MyObject1(5); });
m.def("make_myobject1_2", []() -> ref<MyObject1> { return ref<MyObject1>(new MyObject1(5)); });
m.def("print_object_1", [](const Object *obj) { py::print(obj->toString()); });
m.def("print_object_2", [](ref<Object> obj) { py::print(obj->toString()); });
m.def("print_object_3", [](const ref<Object> &obj) { py::print(obj->toString()); });
@@ -360,7 +360,7 @@ TEST_SUBMODULE(smart_ptr, m) {
// test_smart_ptr_refcounting
m.def("test_object1_refcounting", []() {
ref<MyObject1> o = new MyObject1(0);
auto o = ref<MyObject1>(new MyObject1(0));
bool good = o->getRefCount() == 1;
py::object o2 = py::cast(o, py::return_value_policy::reference);
// always request (partial) ownership for objects with intrusive

View File

@@ -45,7 +45,8 @@ PYBIND11_MAKE_OPAQUE(std::vector<std::string, std::allocator<std::string>>);
/// Issue #528: templated constructor
struct TplCtorClass {
template <typename T> TplCtorClass(const T &) { }
template <typename T>
explicit TplCtorClass(const T &) {}
bool operator==(const TplCtorClass &) const { return true; }
};

View File

@@ -18,7 +18,7 @@
class El {
public:
El() = delete;
El(int v) : a(v) { }
explicit El(int v) : a(v) {}
int a;
};

View File

@@ -37,33 +37,35 @@ struct Animal
struct Dog : Animal
{
Dog(const std::string& _name, Kind _kind = Kind::Dog) : Animal(_name, _kind) {}
explicit Dog(const std::string &_name, Kind _kind = Kind::Dog) : Animal(_name, _kind) {}
std::string bark() const { return name_of_kind(kind) + " " + name + " goes " + sound; }
std::string sound = "WOOF!";
};
struct Labrador : Dog
{
Labrador(const std::string& _name, int _excitement = 9001)
explicit Labrador(const std::string &_name, int _excitement = 9001)
: Dog(_name, Kind::Labrador), excitement(_excitement) {}
int excitement;
};
struct Chihuahua : Dog
{
Chihuahua(const std::string& _name) : Dog(_name, Kind::Chihuahua) { sound = "iyiyiyiyiyi"; }
explicit Chihuahua(const std::string &_name) : Dog(_name, Kind::Chihuahua) {
sound = "iyiyiyiyiyi";
}
std::string bark() const { return Dog::bark() + " and runs in circles"; }
};
struct Cat : Animal
{
Cat(const std::string& _name, Kind _kind = Kind::Cat) : Animal(_name, _kind) {}
explicit Cat(const std::string &_name, Kind _kind = Kind::Cat) : Animal(_name, _kind) {}
std::string purr() const { return "mrowr"; }
};
struct Panther : Cat
{
Panther(const std::string& _name) : Cat(_name, Kind::Panther) {}
explicit Panther(const std::string &_name) : Cat(_name, Kind::Panther) {}
std::string purr() const { return "mrrrRRRRRR"; }
};

View File

@@ -15,7 +15,7 @@
/* This is an example class that we'll want to be able to extend from Python */
class ExampleVirt {
public:
ExampleVirt(int state) : state(state) { print_created(this, state); }
explicit ExampleVirt(int state) : state(state) { print_created(this, state); }
ExampleVirt(const ExampleVirt &e) : state(e.state) { print_copy_created(this); }
ExampleVirt(ExampleVirt &&e) noexcept : state(e.state) {
print_move_created(this);