Unverified Commit 6abf2baa authored by Ralf W. Grosse-Kunstleve's avatar Ralf W. Grosse-Kunstleve Committed by GitHub
Browse files

CodeHealth: Enabling clang-tidy google-explicit-constructor (#3250)

* Adding google-explicit-constructor to .clang-tidy

* clang-tidy explicit attr.h (all automatic)

* clang-tidy explicit cast.h (all automatic)

* clang-tidy detail/init.h (1 NOLINT)

* clang-tidy detail/type_caster_base.h (2 NOLINT)

* clang-tidy pybind11.h (7 NOLINT)

* clang-tidy detail/common.h (3 NOLINT)

* clang-tidy detail/descr.h (2 NOLINT)

* clang-tidy pytypes.h (23 NOLINT, only 1 explicit)

* clang-tidy eigen.h (7 NOLINT, 0 explicit)

* Adding 2 explicit in functional.h

* Adding 4 explicit in iostream.h

* clang-tidy numpy.h (1 NOLINT, 1 explicit)

* clang-tidy embed.h (0 NOLINT, 1 explicit)

* clang-tidy tests/local_bindings.h (0 NOLINT, 4 explicit)

* clang-tidy tests/pybind11_cross_module_tests.cpp (0 NOLINT, 1 explicit)

* clang-tidy tests/pybind11_tests.h (0 NOLINT, 2 explicit)

* clang-tidy tests/test_buffers.cpp (0 NOLINT, 2 explicit)

* clang-tidy tests/test_builtin_casters.cpp (0 NOLINT, 4 explicit)

* clang-tidy tests/test_class.cpp (0 NOLINT, 6 explicit)

* clang-tidy tests/test_copy_move.cpp (0 NOLINT, 7 explicit)

* clang-tidy tests/test_embed/external_module.cpp (0 NOLINT, 1 explicit)

* clang-tidy tests/test_embed/test_interpreter.cpp (0 NOLINT, 1 explicit)

* clang-tidy tests/object.h (0 NOLINT, 2 explicit)

* clang-tidy batch of fully automatic fixes.

* Workaround for MSVC 19.16.27045.0 C++17 Python 2 C++ syntax error.
parent 39a0aac8
...@@ -5,6 +5,7 @@ Checks: ' ...@@ -5,6 +5,7 @@ Checks: '
cppcoreguidelines-init-variables, cppcoreguidelines-init-variables,
cppcoreguidelines-slicing, cppcoreguidelines-slicing,
clang-analyzer-optin.cplusplus.VirtualCall, clang-analyzer-optin.cplusplus.VirtualCall,
google-explicit-constructor,
llvm-namespace-comment, llvm-namespace-comment,
misc-misplaced-const, misc-misplaced-const,
misc-non-copyable-objects, misc-non-copyable-objects,
......
...@@ -18,7 +18,9 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) ...@@ -18,7 +18,9 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
/// @{ /// @{
/// Annotation for methods /// Annotation for methods
struct is_method { handle class_; is_method(const handle &c) : class_(c) { } }; struct is_method { handle class_;
explicit is_method(const handle &c) : class_(c) {}
};
/// Annotation for operators /// Annotation for operators
struct is_operator { }; struct is_operator { };
...@@ -27,16 +29,24 @@ struct is_operator { }; ...@@ -27,16 +29,24 @@ struct is_operator { };
struct is_final { }; struct is_final { };
/// Annotation for parent scope /// Annotation for parent scope
struct scope { handle value; scope(const handle &s) : value(s) { } }; struct scope { handle value;
explicit scope(const handle &s) : value(s) {}
};
/// Annotation for documentation /// Annotation for documentation
struct doc { const char *value; doc(const char *value) : value(value) { } }; struct doc { const char *value;
explicit doc(const char *value) : value(value) {}
};
/// Annotation for function names /// Annotation for function names
struct name { const char *value; name(const char *value) : value(value) { } }; struct name { const char *value;
explicit name(const char *value) : value(value) {}
};
/// Annotation indicating that a function is an overload associated with a given "sibling" /// Annotation indicating that a function is an overload associated with a given "sibling"
struct sibling { handle value; sibling(const handle &value) : value(value.ptr()) { } }; struct sibling { handle value;
explicit sibling(const handle &value) : value(value.ptr()) {}
};
/// Annotation indicating that a class derives from another given type /// Annotation indicating that a class derives from another given type
template <typename T> struct base { template <typename T> struct base {
...@@ -70,7 +80,9 @@ struct metaclass { ...@@ -70,7 +80,9 @@ struct metaclass {
}; };
/// Annotation that marks a class as local to the module: /// Annotation that marks a class as local to the module:
struct module_local { const bool value; constexpr module_local(bool v = true) : value(v) { } }; struct module_local { const bool value;
constexpr explicit module_local(bool v = true) : value(v) {}
};
/// Annotation to mark enums as an arithmetic type /// Annotation to mark enums as an arithmetic type
struct arithmetic { }; struct arithmetic { };
......
...@@ -82,7 +82,7 @@ public: ...@@ -82,7 +82,7 @@ public:
return caster_t::cast(&src.get(), policy, parent); return caster_t::cast(&src.get(), policy, parent);
} }
template <typename T> using cast_op_type = std::reference_wrapper<type>; template <typename T> using cast_op_type = std::reference_wrapper<type>;
operator std::reference_wrapper<type>() { return cast_op<type &>(subcaster); } explicit operator std::reference_wrapper<type>() { return cast_op<type &>(subcaster); }
}; };
#define PYBIND11_TYPE_CASTER(type, py_name) \ #define PYBIND11_TYPE_CASTER(type, py_name) \
...@@ -279,7 +279,7 @@ public: ...@@ -279,7 +279,7 @@ public:
} }
template <typename T> using cast_op_type = void*&; template <typename T> using cast_op_type = void*&;
operator void *&() { return value; } explicit operator void *&() { return value; }
static constexpr auto name = _("capsule"); static constexpr auto name = _("capsule");
private: private:
void *value = nullptr; void *value = nullptr;
...@@ -487,8 +487,10 @@ public: ...@@ -487,8 +487,10 @@ public:
return StringCaster::cast(StringType(1, src), policy, parent); return StringCaster::cast(StringType(1, src), policy, parent);
} }
operator CharT*() { return none ? nullptr : const_cast<CharT *>(static_cast<StringType &>(str_caster).c_str()); } explicit operator CharT *() {
operator CharT&() { return none ? nullptr : const_cast<CharT *>(static_cast<StringType &>(str_caster).c_str());
}
explicit operator CharT &() {
if (none) if (none)
throw value_error("Cannot convert None to a character"); throw value_error("Cannot convert None to a character");
...@@ -581,8 +583,8 @@ public: ...@@ -581,8 +583,8 @@ public:
template <typename T> using cast_op_type = type; template <typename T> using cast_op_type = type;
operator type() & { return implicit_cast(indices{}); } explicit operator type() & { return implicit_cast(indices{}); }
operator type() && { return std::move(*this).implicit_cast(indices{}); } explicit operator type() && { return std::move(*this).implicit_cast(indices{}); }
protected: protected:
template <size_t... Is> template <size_t... Is>
......
...@@ -918,6 +918,7 @@ public: ...@@ -918,6 +918,7 @@ public:
// Implicit conversion constructor from any arbitrary container type with values convertible to T // Implicit conversion constructor from any arbitrary container type with values convertible to T
template <typename Container, typename = enable_if_t<std::is_convertible<decltype(*std::begin(std::declval<const Container &>())), T>::value>> template <typename Container, typename = enable_if_t<std::is_convertible<decltype(*std::begin(std::declval<const Container &>())), T>::value>>
// NOLINTNEXTLINE(google-explicit-constructor)
any_container(const Container &c) : any_container(std::begin(c), std::end(c)) { } any_container(const Container &c) : any_container(std::begin(c), std::end(c)) { }
// initializer_list's aren't deducible, so don't get matched by the above template; we need this // initializer_list's aren't deducible, so don't get matched by the above template; we need this
...@@ -926,9 +927,11 @@ public: ...@@ -926,9 +927,11 @@ public:
any_container(const std::initializer_list<TIn> &c) : any_container(c.begin(), c.end()) { } any_container(const std::initializer_list<TIn> &c) : any_container(c.begin(), c.end()) { }
// Avoid copying if given an rvalue vector of the correct type. // Avoid copying if given an rvalue vector of the correct type.
// NOLINTNEXTLINE(google-explicit-constructor)
any_container(std::vector<T> &&v) : v(std::move(v)) { } any_container(std::vector<T> &&v) : v(std::move(v)) { }
// Moves the vector out of an rvalue any_container // Moves the vector out of an rvalue any_container
// NOLINTNEXTLINE(google-explicit-constructor)
operator std::vector<T> &&() && { return std::move(v); } operator std::vector<T> &&() && { return std::move(v); }
// Dereferencing obtains a reference to the underlying vector // Dereferencing obtains a reference to the underlying vector
......
...@@ -26,12 +26,14 @@ struct descr { ...@@ -26,12 +26,14 @@ struct descr {
char text[N + 1]{'\0'}; char text[N + 1]{'\0'};
constexpr descr() = default; constexpr descr() = default;
// NOLINTNEXTLINE(google-explicit-constructor)
constexpr descr(char const (&s)[N+1]) : descr(s, make_index_sequence<N>()) { } constexpr descr(char const (&s)[N+1]) : descr(s, make_index_sequence<N>()) { }
template <size_t... Is> template <size_t... Is>
constexpr descr(char const (&s)[N+1], index_sequence<Is...>) : text{s[Is]..., '\0'} { } constexpr descr(char const (&s)[N+1], index_sequence<Is...>) : text{s[Is]..., '\0'} { }
template <typename... Chars> template <typename... Chars>
// NOLINTNEXTLINE(google-explicit-constructor)
constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} { } constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} { }
static constexpr std::array<const std::type_info *, sizeof...(Ts) + 1> types() { static constexpr std::array<const std::type_info *, sizeof...(Ts) + 1> types() {
......
...@@ -23,7 +23,7 @@ public: ...@@ -23,7 +23,7 @@ public:
} }
template <typename> using cast_op_type = value_and_holder &; template <typename> using cast_op_type = value_and_holder &;
operator value_and_holder &() { return *value; } explicit operator value_and_holder &() { return *value; }
static constexpr auto name = _<value_and_holder>(); static constexpr auto name = _<value_and_holder>();
private: private:
...@@ -222,7 +222,8 @@ template <typename Func, typename Return, typename... Args> ...@@ -222,7 +222,8 @@ template <typename Func, typename Return, typename... Args>
struct factory<Func, void_type (*)(), Return(Args...)> { struct factory<Func, void_type (*)(), Return(Args...)> {
remove_reference_t<Func> class_factory; remove_reference_t<Func> class_factory;
factory(Func &&f) : class_factory(std::forward<Func>(f)) { } // NOLINTNEXTLINE(google-explicit-constructor)
factory(Func &&f) : class_factory(std::forward<Func>(f)) {}
// The given class either has no alias or has no separate alias factory; // The given class either has no alias or has no separate alias factory;
// this always constructs the class itself. If the class is registered with an alias // this always constructs the class itself. If the class is registered with an alias
......
...@@ -225,7 +225,7 @@ struct value_and_holder { ...@@ -225,7 +225,7 @@ struct value_and_holder {
value_and_holder() = default; value_and_holder() = default;
// Used for past-the-end iterator // Used for past-the-end iterator
value_and_holder(size_t index) : index{index} {} explicit value_and_holder(size_t index) : index{index} {}
template <typename V = void> V *&value_ptr() const { template <typename V = void> V *&value_ptr() const {
return reinterpret_cast<V *&>(vh[0]); return reinterpret_cast<V *&>(vh[0]);
...@@ -274,7 +274,8 @@ private: ...@@ -274,7 +274,8 @@ private:
const type_vec &tinfo; const type_vec &tinfo;
public: public:
values_and_holders(instance *inst) : inst{inst}, tinfo(all_type_info(Py_TYPE(inst))) {} explicit values_and_holders(instance *inst)
: inst{inst}, tinfo(all_type_info(Py_TYPE(inst))) {}
struct iterator { struct iterator {
private: private:
...@@ -290,7 +291,8 @@ public: ...@@ -290,7 +291,8 @@ public:
0 /* index */) 0 /* index */)
{} {}
// Past-the-end iterator: // Past-the-end iterator:
iterator(size_t end) : curr(end) {} explicit iterator(size_t end) : curr(end) {}
public: public:
bool operator==(const iterator &other) const { return curr.index == other.curr.index; } bool operator==(const iterator &other) const { return curr.index == other.curr.index; }
bool operator!=(const iterator &other) const { return curr.index != other.curr.index; } bool operator!=(const iterator &other) const { return curr.index != other.curr.index; }
...@@ -491,11 +493,11 @@ inline PyObject *make_new_instance(PyTypeObject *type); ...@@ -491,11 +493,11 @@ inline PyObject *make_new_instance(PyTypeObject *type);
class type_caster_generic { class type_caster_generic {
public: public:
PYBIND11_NOINLINE type_caster_generic(const std::type_info &type_info) PYBIND11_NOINLINE explicit type_caster_generic(const std::type_info &type_info)
: typeinfo(get_type_info(type_info)), cpptype(&type_info) { } : typeinfo(get_type_info(type_info)), cpptype(&type_info) {}
type_caster_generic(const type_info *typeinfo) explicit type_caster_generic(const type_info *typeinfo)
: typeinfo(typeinfo), cpptype(typeinfo ? typeinfo->cpptype : nullptr) { } : typeinfo(typeinfo), cpptype(typeinfo ? typeinfo->cpptype : nullptr) {}
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
return load_impl<type_caster_generic>(src, convert); return load_impl<type_caster_generic>(src, convert);
...@@ -923,7 +925,9 @@ public: ...@@ -923,7 +925,9 @@ public:
template <typename T> using cast_op_type = detail::cast_op_type<T>; template <typename T> using cast_op_type = detail::cast_op_type<T>;
// NOLINTNEXTLINE(google-explicit-constructor)
operator itype*() { return (type *) value; } operator itype*() { return (type *) value; }
// NOLINTNEXTLINE(google-explicit-constructor)
operator itype&() { if (!value) throw reference_cast_error(); return *((itype *) value); } operator itype&() { if (!value) throw reference_cast_error(); return *((itype *) value); }
protected: protected:
......
...@@ -61,6 +61,7 @@ template <bool EigenRowMajor> struct EigenConformable { ...@@ -61,6 +61,7 @@ template <bool EigenRowMajor> struct EigenConformable {
EigenDStride stride{0, 0}; // Only valid if negativestrides is false! EigenDStride stride{0, 0}; // Only valid if negativestrides is false!
bool negativestrides = false; // If true, do not use stride! bool negativestrides = false; // If true, do not use stride!
// NOLINTNEXTLINE(google-explicit-constructor)
EigenConformable(bool fits = false) : conformable{fits} {} EigenConformable(bool fits = false) : conformable{fits} {}
// Matrix type: // Matrix type:
EigenConformable(EigenIndex r, EigenIndex c, EigenConformable(EigenIndex r, EigenIndex c,
...@@ -88,6 +89,7 @@ template <bool EigenRowMajor> struct EigenConformable { ...@@ -88,6 +89,7 @@ template <bool EigenRowMajor> struct EigenConformable {
(props::outer_stride == Eigen::Dynamic || props::outer_stride == stride.outer() || (props::outer_stride == Eigen::Dynamic || props::outer_stride == stride.outer() ||
(EigenRowMajor ? rows : cols) == 1); (EigenRowMajor ? rows : cols) == 1);
} }
// NOLINTNEXTLINE(google-explicit-constructor)
operator bool() const { return conformable; } operator bool() const { return conformable; }
}; };
...@@ -326,8 +328,11 @@ public: ...@@ -326,8 +328,11 @@ public:
static constexpr auto name = props::descriptor; static constexpr auto name = props::descriptor;
// NOLINTNEXTLINE(google-explicit-constructor)
operator Type*() { return &value; } operator Type*() { return &value; }
// NOLINTNEXTLINE(google-explicit-constructor)
operator Type&() { return value; } operator Type&() { return value; }
// NOLINTNEXTLINE(google-explicit-constructor)
operator Type&&() && { return std::move(value); } operator Type&&() && { return std::move(value); }
template <typename T> using cast_op_type = movable_cast_op_type<T>; template <typename T> using cast_op_type = movable_cast_op_type<T>;
...@@ -451,7 +456,9 @@ public: ...@@ -451,7 +456,9 @@ public:
return true; return true;
} }
// NOLINTNEXTLINE(google-explicit-constructor)
operator Type*() { return ref.get(); } operator Type*() { return ref.get(); }
// NOLINTNEXTLINE(google-explicit-constructor)
operator Type&() { return *ref; } operator Type&() { return *ref; }
template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>; template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>;
......
...@@ -260,7 +260,7 @@ inline void finalize_interpreter() { ...@@ -260,7 +260,7 @@ inline void finalize_interpreter() {
\endrst */ \endrst */
class scoped_interpreter { class scoped_interpreter {
public: public:
scoped_interpreter(bool init_signal_handlers = true, explicit scoped_interpreter(bool init_signal_handlers = true,
int argc = 0, int argc = 0,
const char *const *argv = nullptr, const char *const *argv = nullptr,
bool add_program_dir_to_path = true) { bool add_program_dir_to_path = true) {
......
...@@ -69,6 +69,10 @@ public: ...@@ -69,6 +69,10 @@ public:
// ensure GIL is held during functor destruction // ensure GIL is held during functor destruction
struct func_handle { struct func_handle {
function f; function f;
#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17) && PY_MAJOR_VERSION < 3)
// This triggers a syntax error under very special conditions (very weird indeed).
explicit
#endif
func_handle(function &&f_) noexcept : f(std::move(f_)) {} func_handle(function &&f_) noexcept : f(std::move(f_)) {}
func_handle(const func_handle &f_) { operator=(f_); } func_handle(const func_handle &f_) { operator=(f_); }
func_handle &operator=(const func_handle &f_) { func_handle &operator=(const func_handle &f_) {
...@@ -85,7 +89,7 @@ public: ...@@ -85,7 +89,7 @@ public:
// to emulate 'move initialization capture' in C++11 // to emulate 'move initialization capture' in C++11
struct func_wrapper { struct func_wrapper {
func_handle hfunc; func_handle hfunc;
func_wrapper(func_handle &&hf) noexcept : hfunc(std::move(hf)) {} explicit func_wrapper(func_handle &&hf) noexcept : hfunc(std::move(hf)) {}
Return operator()(Args... args) const { Return operator()(Args... args) const {
gil_scoped_acquire acq; gil_scoped_acquire acq;
object retval(hfunc.f(std::forward<Args>(args)...)); object retval(hfunc.f(std::forward<Args>(args)...));
......
...@@ -123,7 +123,7 @@ private: ...@@ -123,7 +123,7 @@ private:
} }
public: public:
pythonbuf(const object &pyostream, size_t buffer_size = 1024) explicit pythonbuf(const object &pyostream, size_t buffer_size = 1024)
: buf_size(buffer_size), d_buffer(new char[buf_size]), pywrite(pyostream.attr("write")), : buf_size(buffer_size), d_buffer(new char[buf_size]), pywrite(pyostream.attr("write")),
pyflush(pyostream.attr("flush")) { pyflush(pyostream.attr("flush")) {
setp(d_buffer.get(), d_buffer.get() + buf_size - 1); setp(d_buffer.get(), d_buffer.get() + buf_size - 1);
...@@ -171,8 +171,9 @@ protected: ...@@ -171,8 +171,9 @@ protected:
detail::pythonbuf buffer; detail::pythonbuf buffer;
public: public:
scoped_ostream_redirect(std::ostream &costream = std::cout, explicit scoped_ostream_redirect(std::ostream &costream = std::cout,
const object &pyostream = module_::import("sys").attr("stdout")) const object &pyostream
= module_::import("sys").attr("stdout"))
: costream(costream), buffer(pyostream) { : costream(costream), buffer(pyostream) {
old = costream.rdbuf(&buffer); old = costream.rdbuf(&buffer);
} }
...@@ -201,8 +202,9 @@ public: ...@@ -201,8 +202,9 @@ public:
\endrst */ \endrst */
class scoped_estream_redirect : public scoped_ostream_redirect { class scoped_estream_redirect : public scoped_ostream_redirect {
public: public:
scoped_estream_redirect(std::ostream &costream = std::cerr, explicit scoped_estream_redirect(std::ostream &costream = std::cerr,
const object &pyostream = module_::import("sys").attr("stderr")) const object &pyostream
= module_::import("sys").attr("stderr"))
: scoped_ostream_redirect(costream, pyostream) {} : scoped_ostream_redirect(costream, pyostream) {}
}; };
...@@ -217,7 +219,7 @@ class OstreamRedirect { ...@@ -217,7 +219,7 @@ class OstreamRedirect {
std::unique_ptr<scoped_estream_redirect> redirect_stderr; std::unique_ptr<scoped_estream_redirect> redirect_stderr;
public: public:
OstreamRedirect(bool do_stdout = true, bool do_stderr = true) explicit OstreamRedirect(bool do_stdout = true, bool do_stderr = true)
: do_stdout_(do_stdout), do_stderr_(do_stderr) {} : do_stdout_(do_stdout), do_stderr_(do_stderr) {}
void enter() { void enter() {
......
...@@ -477,7 +477,7 @@ public: ...@@ -477,7 +477,7 @@ public:
m_ptr = from_args(pybind11::str(format)).release().ptr(); m_ptr = from_args(pybind11::str(format)).release().ptr();
} }
dtype(const char *format) : dtype(std::string(format)) { } explicit dtype(const char *format) : dtype(std::string(format)) {}
dtype(list names, list formats, list offsets, ssize_t itemsize) { dtype(list names, list formats, list offsets, ssize_t itemsize) {
dict args; dict args;
...@@ -894,6 +894,7 @@ public: ...@@ -894,6 +894,7 @@ public:
if (!is_borrowed) Py_XDECREF(h.ptr()); if (!is_borrowed) Py_XDECREF(h.ptr());
} }
// NOLINTNEXTLINE(google-explicit-constructor)
array_t(const object &o) : array(raw_array_t(o.ptr()), stolen_t{}) { array_t(const object &o) : array(raw_array_t(o.ptr()), stolen_t{}) {
if (!m_ptr) throw error_already_set(); if (!m_ptr) throw error_already_set();
} }
......
...@@ -81,10 +81,12 @@ PYBIND11_NAMESPACE_END(detail) ...@@ -81,10 +81,12 @@ PYBIND11_NAMESPACE_END(detail)
class cpp_function : public function { class cpp_function : public function {
public: public:
cpp_function() = default; cpp_function() = default;
// NOLINTNEXTLINE(google-explicit-constructor)
cpp_function(std::nullptr_t) { } cpp_function(std::nullptr_t) { }
/// Construct a cpp_function from a vanilla function pointer /// Construct a cpp_function from a vanilla function pointer
template <typename Return, typename... Args, typename... Extra> template <typename Return, typename... Args, typename... Extra>
// NOLINTNEXTLINE(google-explicit-constructor)
cpp_function(Return (*f)(Args...), const Extra&... extra) { cpp_function(Return (*f)(Args...), const Extra&... extra) {
initialize(f, f, extra...); initialize(f, f, extra...);
} }
...@@ -92,6 +94,7 @@ public: ...@@ -92,6 +94,7 @@ public:
/// Construct a cpp_function from a lambda function (possibly with internal state) /// Construct a cpp_function from a lambda function (possibly with internal state)
template <typename Func, typename... Extra, template <typename Func, typename... Extra,
typename = detail::enable_if_t<detail::is_lambda<Func>::value>> typename = detail::enable_if_t<detail::is_lambda<Func>::value>>
// NOLINTNEXTLINE(google-explicit-constructor)
cpp_function(Func &&f, const Extra&... extra) { cpp_function(Func &&f, const Extra&... extra) {
initialize(std::forward<Func>(f), initialize(std::forward<Func>(f),
(detail::function_signature_t<Func> *) nullptr, extra...); (detail::function_signature_t<Func> *) nullptr, extra...);
...@@ -99,6 +102,7 @@ public: ...@@ -99,6 +102,7 @@ public:
/// Construct a cpp_function from a class method (non-const, no ref-qualifier) /// Construct a cpp_function from a class method (non-const, no ref-qualifier)
template <typename Return, typename Class, typename... Arg, typename... Extra> template <typename Return, typename Class, typename... Arg, typename... Extra>
// NOLINTNEXTLINE(google-explicit-constructor)
cpp_function(Return (Class::*f)(Arg...), const Extra&... extra) { cpp_function(Return (Class::*f)(Arg...), const Extra&... extra) {
initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); }, initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); },
(Return (*) (Class *, Arg...)) nullptr, extra...); (Return (*) (Class *, Arg...)) nullptr, extra...);
...@@ -108,6 +112,7 @@ public: ...@@ -108,6 +112,7 @@ public:
/// A copy of the overload for non-const functions without explicit ref-qualifier /// A copy of the overload for non-const functions without explicit ref-qualifier
/// but with an added `&`. /// but with an added `&`.
template <typename Return, typename Class, typename... Arg, typename... Extra> template <typename Return, typename Class, typename... Arg, typename... Extra>
// NOLINTNEXTLINE(google-explicit-constructor)
cpp_function(Return (Class::*f)(Arg...)&, const Extra&... extra) { cpp_function(Return (Class::*f)(Arg...)&, const Extra&... extra) {
initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); }, initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); },
(Return (*) (Class *, Arg...)) nullptr, extra...); (Return (*) (Class *, Arg...)) nullptr, extra...);
...@@ -115,6 +120,7 @@ public: ...@@ -115,6 +120,7 @@ public:
/// Construct a cpp_function from a class method (const, no ref-qualifier) /// Construct a cpp_function from a class method (const, no ref-qualifier)
template <typename Return, typename Class, typename... Arg, typename... Extra> template <typename Return, typename Class, typename... Arg, typename... Extra>
// NOLINTNEXTLINE(google-explicit-constructor)
cpp_function(Return (Class::*f)(Arg...) const, const Extra&... extra) { cpp_function(Return (Class::*f)(Arg...) const, const Extra&... extra) {
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); }, initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); },
(Return (*)(const Class *, Arg ...)) nullptr, extra...); (Return (*)(const Class *, Arg ...)) nullptr, extra...);
...@@ -124,6 +130,7 @@ public: ...@@ -124,6 +130,7 @@ public:
/// A copy of the overload for const functions without explicit ref-qualifier /// A copy of the overload for const functions without explicit ref-qualifier
/// but with an added `&`. /// but with an added `&`.
template <typename Return, typename Class, typename... Arg, typename... Extra> template <typename Return, typename Class, typename... Arg, typename... Extra>
// NOLINTNEXTLINE(google-explicit-constructor)
cpp_function(Return (Class::*f)(Arg...) const&, const Extra&... extra) { cpp_function(Return (Class::*f)(Arg...) const&, const Extra&... extra) {
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); }, initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
(Return (*)(const Class *, Arg ...)) nullptr, extra...); (Return (*)(const Class *, Arg ...)) nullptr, extra...);
...@@ -2034,7 +2041,7 @@ template <return_value_policy Policy = return_value_policy::reference_internal, ...@@ -2034,7 +2041,7 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
template <typename InputType, typename OutputType> void implicitly_convertible() { template <typename InputType, typename OutputType> void implicitly_convertible() {
struct set_flag { struct set_flag {
bool &flag; bool &flag;
set_flag(bool &flag_) : flag(flag_) { flag_ = true; } explicit set_flag(bool &flag_) : flag(flag_) { flag_ = true; }
~set_flag() { flag = false; } ~set_flag() { flag = false; }
}; };
auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject * { auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject * {
......
...@@ -178,6 +178,7 @@ public: ...@@ -178,6 +178,7 @@ public:
/// The default constructor creates a handle with a ``nullptr``-valued pointer /// The default constructor creates a handle with a ``nullptr``-valued pointer
handle() = default; handle() = default;
/// Creates a ``handle`` from the given raw Python object pointer /// Creates a ``handle`` from the given raw Python object pointer
// NOLINTNEXTLINE(google-explicit-constructor)
handle(PyObject *ptr) : m_ptr(ptr) { } // Allow implicit conversion from PyObject* handle(PyObject *ptr) : m_ptr(ptr) { } // Allow implicit conversion from PyObject*
/// Return the underlying ``PyObject *`` pointer /// Return the underlying ``PyObject *`` pointer
...@@ -612,6 +613,7 @@ public: ...@@ -612,6 +613,7 @@ public:
return obj.contains(key); return obj.contains(key);
} }
// NOLINTNEXTLINE(google-explicit-constructor)
operator object() const { return get_cache(); } operator object() const { return get_cache(); }
PyObject *ptr() const { return get_cache().ptr(); } PyObject *ptr() const { return get_cache().ptr(); }
template <typename T> T cast() const { return get_cache().template cast<T>(); } template <typename T> T cast() const { return get_cache().template cast<T>(); }
...@@ -761,6 +763,7 @@ template <typename T> ...@@ -761,6 +763,7 @@ template <typename T>
struct arrow_proxy { struct arrow_proxy {
T value; T value;
// NOLINTNEXTLINE(google-explicit-constructor)
arrow_proxy(T &&value) noexcept : value(std::move(value)) { } arrow_proxy(T &&value) noexcept : value(std::move(value)) { }
T *operator->() const { return &value; } T *operator->() const { return &value; }
}; };
...@@ -909,14 +912,17 @@ PYBIND11_NAMESPACE_END(detail) ...@@ -909,14 +912,17 @@ PYBIND11_NAMESPACE_END(detail)
bool check() const { return m_ptr != nullptr && (CheckFun(m_ptr) != 0); } \ bool check() const { return m_ptr != nullptr && (CheckFun(m_ptr) != 0); } \
static bool check_(handle h) { return h.ptr() != nullptr && CheckFun(h.ptr()); } \ static bool check_(handle h) { return h.ptr() != nullptr && CheckFun(h.ptr()); } \
template <typename Policy_> \ template <typename Policy_> \
/* NOLINTNEXTLINE(google-explicit-constructor) */ \
Name(const ::pybind11::detail::accessor<Policy_> &a) : Name(object(a)) { } Name(const ::pybind11::detail::accessor<Policy_> &a) : Name(object(a)) { }
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun) \ #define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun) \
PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \ PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
/* This is deliberately not 'explicit' to allow implicit conversion from object: */ \ /* This is deliberately not 'explicit' to allow implicit conversion from object: */ \
/* NOLINTNEXTLINE(google-explicit-constructor) */ \
Name(const object &o) \ Name(const object &o) \
: Parent(check_(o) ? o.inc_ref().ptr() : ConvertFun(o.ptr()), stolen_t{}) \ : Parent(check_(o) ? o.inc_ref().ptr() : ConvertFun(o.ptr()), stolen_t{}) \
{ if (!m_ptr) throw error_already_set(); } \ { if (!m_ptr) throw error_already_set(); } \
/* NOLINTNEXTLINE(google-explicit-constructor) */ \
Name(object &&o) \ Name(object &&o) \
: Parent(check_(o) ? o.release().ptr() : ConvertFun(o.ptr()), stolen_t{}) \ : Parent(check_(o) ? o.release().ptr() : ConvertFun(o.ptr()), stolen_t{}) \
{ if (!m_ptr) throw error_already_set(); } { if (!m_ptr) throw error_already_set(); }
...@@ -933,8 +939,10 @@ PYBIND11_NAMESPACE_END(detail) ...@@ -933,8 +939,10 @@ PYBIND11_NAMESPACE_END(detail)
#define PYBIND11_OBJECT(Name, Parent, CheckFun) \ #define PYBIND11_OBJECT(Name, Parent, CheckFun) \
PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \ PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
/* This is deliberately not 'explicit' to allow implicit conversion from object: */ \ /* This is deliberately not 'explicit' to allow implicit conversion from object: */ \
/* NOLINTNEXTLINE(google-explicit-constructor) */ \
Name(const object &o) : Parent(o) \ Name(const object &o) : Parent(o) \
{ if (m_ptr && !check_(m_ptr)) throw PYBIND11_OBJECT_CHECK_FAILED(Name, m_ptr); } \ { if (m_ptr && !check_(m_ptr)) throw PYBIND11_OBJECT_CHECK_FAILED(Name, m_ptr); } \
/* NOLINTNEXTLINE(google-explicit-constructor) */ \
Name(object &&o) : Parent(std::move(o)) \ Name(object &&o) : Parent(std::move(o)) \
{ if (m_ptr && !check_(m_ptr)) throw PYBIND11_OBJECT_CHECK_FAILED(Name, m_ptr); } { if (m_ptr && !check_(m_ptr)) throw PYBIND11_OBJECT_CHECK_FAILED(Name, m_ptr); }
...@@ -1056,11 +1064,13 @@ public: ...@@ -1056,11 +1064,13 @@ public:
} }
// 'explicit' is explicitly omitted from the following constructors to allow implicit conversion to py::str from C++ string-like objects // 'explicit' is explicitly omitted from the following constructors to allow implicit conversion to py::str from C++ string-like objects
// NOLINTNEXTLINE(google-explicit-constructor)
str(const char *c = "") str(const char *c = "")
: object(PyUnicode_FromString(c), stolen_t{}) { : object(PyUnicode_FromString(c), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate string object!"); if (!m_ptr) pybind11_fail("Could not allocate string object!");
} }
// NOLINTNEXTLINE(google-explicit-constructor)
str(const std::string &s) : str(s.data(), s.size()) { } str(const std::string &s) : str(s.data(), s.size()) { }
explicit str(const bytes &b); explicit str(const bytes &b);
...@@ -1071,6 +1081,7 @@ public: ...@@ -1071,6 +1081,7 @@ public:
\endrst */ \endrst */
explicit str(handle h) : object(raw_str(h.ptr()), stolen_t{}) { if (!m_ptr) throw error_already_set(); } explicit str(handle h) : object(raw_str(h.ptr()), stolen_t{}) { if (!m_ptr) throw error_already_set(); }
// NOLINTNEXTLINE(google-explicit-constructor)
operator std::string() const { operator std::string() const {
object temp = *this; object temp = *this;
if (PyUnicode_Check(m_ptr)) { if (PyUnicode_Check(m_ptr)) {
...@@ -1118,6 +1129,7 @@ public: ...@@ -1118,6 +1129,7 @@ public:
PYBIND11_OBJECT(bytes, object, PYBIND11_BYTES_CHECK) PYBIND11_OBJECT(bytes, object, PYBIND11_BYTES_CHECK)
// Allow implicit conversion: // Allow implicit conversion:
// NOLINTNEXTLINE(google-explicit-constructor)
bytes(const char *c = "") bytes(const char *c = "")
: object(PYBIND11_BYTES_FROM_STRING(c), stolen_t{}) { : object(PYBIND11_BYTES_FROM_STRING(c), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate bytes object!"); if (!m_ptr) pybind11_fail("Could not allocate bytes object!");
...@@ -1130,10 +1142,12 @@ public: ...@@ -1130,10 +1142,12 @@ public:
} }
// Allow implicit conversion: // Allow implicit conversion:
// NOLINTNEXTLINE(google-explicit-constructor)
bytes(const std::string &s) : bytes(s.data(), s.size()) { } bytes(const std::string &s) : bytes(s.data(), s.size()) { }
explicit bytes(const pybind11::str &s); explicit bytes(const pybind11::str &s);
// NOLINTNEXTLINE(google-explicit-constructor)
operator std::string() const { operator std::string() const {
char *buffer = nullptr; char *buffer = nullptr;
ssize_t length = 0; ssize_t length = 0;
...@@ -1222,7 +1236,9 @@ public: ...@@ -1222,7 +1236,9 @@ public:
PYBIND11_OBJECT_CVT(bool_, object, PyBool_Check, raw_bool) PYBIND11_OBJECT_CVT(bool_, object, PyBool_Check, raw_bool)
bool_() : object(Py_False, borrowed_t{}) { } bool_() : object(Py_False, borrowed_t{}) { }
// Allow implicit conversion from and to `bool`: // Allow implicit conversion from and to `bool`:
// NOLINTNEXTLINE(google-explicit-constructor)
bool_(bool value) : object(value ? Py_True : Py_False, borrowed_t{}) { } bool_(bool value) : object(value ? Py_True : Py_False, borrowed_t{}) { }
// NOLINTNEXTLINE(google-explicit-constructor)
operator bool() const { return (m_ptr != nullptr) && PyLong_AsLong(m_ptr) != 0; } operator bool() const { return (m_ptr != nullptr) && PyLong_AsLong(m_ptr) != 0; }
private: private:
...@@ -1261,6 +1277,7 @@ public: ...@@ -1261,6 +1277,7 @@ public:
// Allow implicit conversion from C++ integral types: // Allow implicit conversion from C++ integral types:
template <typename T, template <typename T,
detail::enable_if_t<std::is_integral<T>::value, int> = 0> detail::enable_if_t<std::is_integral<T>::value, int> = 0>
// NOLINTNEXTLINE(google-explicit-constructor)
int_(T value) { int_(T value) {
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(T) <= sizeof(long))) { if (PYBIND11_SILENCE_MSVC_C4127(sizeof(T) <= sizeof(long))) {
if (std::is_signed<T>::value) if (std::is_signed<T>::value)
...@@ -1278,6 +1295,7 @@ public: ...@@ -1278,6 +1295,7 @@ public:
template <typename T, template <typename T,
detail::enable_if_t<std::is_integral<T>::value, int> = 0> detail::enable_if_t<std::is_integral<T>::value, int> = 0>
// NOLINTNEXTLINE(google-explicit-constructor)
operator T() const { operator T() const {
return std::is_unsigned<T>::value return std::is_unsigned<T>::value
? detail::as_unsigned<T>(m_ptr) ? detail::as_unsigned<T>(m_ptr)
...@@ -1291,13 +1309,17 @@ class float_ : public object { ...@@ -1291,13 +1309,17 @@ class float_ : public object {
public: public:
PYBIND11_OBJECT_CVT(float_, object, PyFloat_Check, PyNumber_Float) PYBIND11_OBJECT_CVT(float_, object, PyFloat_Check, PyNumber_Float)
// Allow implicit conversion from float/double: // Allow implicit conversion from float/double:
// NOLINTNEXTLINE(google-explicit-constructor)
float_(float value) : object(PyFloat_FromDouble((double) value), stolen_t{}) { float_(float value) : object(PyFloat_FromDouble((double) value), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate float object!"); if (!m_ptr) pybind11_fail("Could not allocate float object!");
} }
// NOLINTNEXTLINE(google-explicit-constructor)
float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen_t{}) { float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate float object!"); if (!m_ptr) pybind11_fail("Could not allocate float object!");
} }
// NOLINTNEXTLINE(google-explicit-constructor)
operator float() const { return (float) PyFloat_AsDouble(m_ptr); } operator float() const { return (float) PyFloat_AsDouble(m_ptr); }
// NOLINTNEXTLINE(google-explicit-constructor)
operator double() const { return (double) PyFloat_AsDouble(m_ptr); } operator double() const { return (double) PyFloat_AsDouble(m_ptr); }
}; };
...@@ -1372,7 +1394,7 @@ public: ...@@ -1372,7 +1394,7 @@ public:
pybind11_fail("Could not set capsule context!"); pybind11_fail("Could not set capsule context!");
} }
capsule(void (*destructor)()) { explicit capsule(void (*destructor)()) {
m_ptr = PyCapsule_New(reinterpret_cast<void *>(destructor), nullptr, [](PyObject *o) { m_ptr = PyCapsule_New(reinterpret_cast<void *>(destructor), nullptr, [](PyObject *o) {
auto destructor = reinterpret_cast<void (*)()>(PyCapsule_GetPointer(o, nullptr)); auto destructor = reinterpret_cast<void (*)()>(PyCapsule_GetPointer(o, nullptr));
destructor(); destructor();
...@@ -1382,6 +1404,7 @@ public: ...@@ -1382,6 +1404,7 @@ public:
pybind11_fail("Could not allocate capsule object!"); pybind11_fail("Could not allocate capsule object!");
} }
// NOLINTNEXTLINE(google-explicit-constructor)
template <typename T> operator T *() const { template <typename T> operator T *() const {
return get_pointer<T>(); return get_pointer<T>();
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
/// Simple class used to test py::local: /// Simple class used to test py::local:
template <int> class LocalBase { template <int> class LocalBase {
public: public:
LocalBase(int i) : i(i) { } explicit LocalBase(int i) : i(i) { }
int i = -1; int i = -1;
}; };
...@@ -75,11 +75,11 @@ py::class_<T> bind_local(Args && ...args) { ...@@ -75,11 +75,11 @@ py::class_<T> bind_local(Args && ...args) {
namespace pets { namespace pets {
class Pet { class Pet {
public: public:
Pet(std::string name) : name_(std::move(name)) {} explicit Pet(std::string name) : name_(std::move(name)) {}
std::string name_; std::string name_;
const std::string &name() const { return name_; } const std::string &name() const { return name_; }
}; };
} // namespace pets } // namespace pets
struct MixGL { int i; MixGL(int i) : i{i} {} }; struct MixGL { int i; explicit MixGL(int i) : i{i} {} };
struct MixGL2 { int i; MixGL2(int i) : i{i} {} }; struct MixGL2 { int i; explicit MixGL2(int i) : i{i} {} };
...@@ -65,7 +65,7 @@ public: ...@@ -65,7 +65,7 @@ public:
ref() : m_ptr(nullptr) { print_default_created(this); track_default_created((ref_tag*) this); } ref() : m_ptr(nullptr) { print_default_created(this); track_default_created((ref_tag*) this); }
/// Construct a reference from a pointer /// 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(); if (m_ptr) ((Object *) m_ptr)->incRef();
print_created(this, "from pointer", m_ptr); track_created((ref_tag*) this, "from pointer"); print_created(this, "from pointer", m_ptr); track_created((ref_tag*) this, "from pointer");
...@@ -165,7 +165,7 @@ public: ...@@ -165,7 +165,7 @@ public:
const T& operator*() const { return *m_ptr; } const T& operator*() const { return *m_ptr; }
/// Return a pointer to the referenced object /// 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 /// Return a const pointer to the referenced object
T* get_ptr() { return m_ptr; } T* get_ptr() { return m_ptr; }
......
...@@ -123,7 +123,7 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) { ...@@ -123,7 +123,7 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
class Dog : public pets::Pet { class Dog : public pets::Pet {
public: 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()) py::class_<pets::Pet>(m, "Pet", py::module_local())
.def("name", &pets::Pet::name); .def("name", &pets::Pet::name);
......
...@@ -16,7 +16,7 @@ class test_initializer { ...@@ -16,7 +16,7 @@ class test_initializer {
using Initializer = void (*)(py::module_ &); using Initializer = void (*)(py::module_ &);
public: public:
test_initializer(Initializer init); explicit test_initializer(Initializer init);
test_initializer(const char *submodule_name, Initializer init); test_initializer(const char *submodule_name, Initializer init);
}; };
...@@ -32,7 +32,7 @@ struct UnregisteredType { }; ...@@ -32,7 +32,7 @@ struct UnregisteredType { };
class UserType { class UserType {
public: public:
UserType() = default; UserType() = default;
UserType(int i) : i(i) { } explicit UserType(int i) : i(i) { }
int value() const { return i; } int value() const { return i; }
void set(int set) { i = set; } void set(int set) { i = set; }
......
...@@ -122,7 +122,7 @@ TEST_SUBMODULE(buffers, m) { ...@@ -122,7 +122,7 @@ TEST_SUBMODULE(buffers, m) {
// test_inherited_protocol // test_inherited_protocol
class SquareMatrix : public Matrix { class SquareMatrix : public Matrix {
public: 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 // Derived classes inherit the buffer protocol and the buffer access function
py::class_<SquareMatrix, Matrix>(m, "SquareMatrix") py::class_<SquareMatrix, Matrix>(m, "SquareMatrix")
...@@ -173,7 +173,7 @@ TEST_SUBMODULE(buffers, m) { ...@@ -173,7 +173,7 @@ TEST_SUBMODULE(buffers, m) {
struct BufferReadOnly { struct BufferReadOnly {
const uint8_t value = 0; const uint8_t value = 0;
BufferReadOnly(uint8_t value): value(value) {} explicit BufferReadOnly(uint8_t value) : value(value) {}
py::buffer_info get_buffer_info() { py::buffer_info get_buffer_info() {
return py::buffer_info(&value, 1); return py::buffer_info(&value, 1);
......
...@@ -25,16 +25,28 @@ class type_caster<ConstRefCasted> { ...@@ -25,16 +25,28 @@ class type_caster<ConstRefCasted> {
// cast operator. // cast operator.
bool load(handle, bool) { return true; } bool load(handle, bool) { return true; }
operator ConstRefCasted &&() { explicit operator ConstRefCasted &&() {
value = {1}; value = {1};
// NOLINTNEXTLINE(performance-move-const-arg) // NOLINTNEXTLINE(performance-move-const-arg)
return std::move(value); return std::move(value);
} }
operator ConstRefCasted&() { value = {2}; return value; } explicit operator ConstRefCasted &() {
operator ConstRefCasted*() { value = {3}; return &value; } value = {2};
return value;
}
explicit operator ConstRefCasted *() {
value = {3};
return &value;
}
operator const ConstRefCasted&() { value = {4}; return value; } explicit operator const ConstRefCasted &() {
operator const ConstRefCasted*() { value = {5}; return &value; } value = {4};
return value;
}
explicit operator const ConstRefCasted *() {
value = {5};
return &value;
}
// custom cast_op to explicitly propagate types to the conversion operators. // custom cast_op to explicitly propagate types to the conversion operators.
template <typename T_> template <typename T_>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment