#include <string_view>
#endif
+#if defined(__cpp_lib_char8_t) && __cpp_lib_char8_t >= 201811L
+# define PYBIND11_HAS_U8STRING
+#endif
+
NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
NAMESPACE_BEGIN(detail)
case return_value_policy::copy:
if (copy_constructor)
valueptr = copy_constructor(src);
- else
- throw cast_error("return_value_policy = copy, but the "
- "object is non-copyable!");
+ else {
+#if defined(NDEBUG)
+ throw cast_error("return_value_policy = copy, but type is "
+ "non-copyable! (compile in debug mode for details)");
+#else
+ std::string type_name(tinfo->cpptype->name());
+ detail::clean_type_id(type_name);
+ throw cast_error("return_value_policy = copy, but type " +
+ type_name + " is non-copyable!");
+#endif
+ }
wrapper->owned = true;
break;
valueptr = move_constructor(src);
else if (copy_constructor)
valueptr = copy_constructor(src);
- else
- throw cast_error("return_value_policy = move, but the "
- "object is neither movable nor copyable!");
+ else {
+#if defined(NDEBUG)
+ throw cast_error("return_value_policy = move, but type is neither "
+ "movable nor copyable! "
+ "(compile in debug mode for details)");
+#else
+ std::string type_name(tinfo->cpptype->name());
+ detail::clean_type_id(type_name);
+ throw cast_error("return_value_policy = move, but type " +
+ type_name + " is neither movable nor copyable!");
+#endif
+ }
wrapper->owned = true;
break;
if (type->operator_new) {
vptr = type->operator_new(type->type_size);
} else {
- #if defined(PYBIND11_CPP17)
+ #if defined(__cpp_aligned_new) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
if (type->type_align > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
vptr = ::operator new(type->type_size,
- (std::align_val_t) type->type_align);
+ std::align_val_t(type->type_align));
else
#endif
vptr = ::operator new(type->type_size);
negation<std::is_same<Container, typename Container::value_type>>
>::value>> : is_copy_constructible<typename Container::value_type> {};
-#if !defined(PYBIND11_CPP17)
-// Likewise for std::pair before C++17 (which mandates that the copy constructor not exist when the
-// two types aren't themselves copy constructible).
+// Likewise for std::pair
+// (after C++17 it is mandatory that the copy constructor not exist when the two types aren't themselves
+// copy constructible, but this can not be relied upon when T1 or T2 are themselves containers).
template <typename T1, typename T2> struct is_copy_constructible<std::pair<T1, T2>>
: all_of<is_copy_constructible<T1>, is_copy_constructible<T2>> {};
-#endif
+
+// The same problems arise with std::is_copy_assignable, so we use the same workaround.
+template <typename T, typename SFINAE = void> struct is_copy_assignable : std::is_copy_assignable<T> {};
+template <typename Container> struct is_copy_assignable<Container, enable_if_t<all_of<
+ std::is_copy_assignable<Container>,
+ std::is_same<typename Container::value_type &, typename Container::reference>
+ >::value>> : is_copy_assignable<typename Container::value_type> {};
+template <typename T1, typename T2> struct is_copy_assignable<std::pair<T1, T2>>
+ : all_of<is_copy_assignable<T1>, is_copy_assignable<T2>> {};
NAMESPACE_END(detail)
template <typename CharT> using is_std_char_type = any_of<
std::is_same<CharT, char>, /* std::string */
+#if defined(PYBIND11_HAS_U8STRING)
+ std::is_same<CharT, char8_t>, /* std::u8string */
+#endif
std::is_same<CharT, char16_t>, /* std::u16string */
std::is_same<CharT, char32_t>, /* std::u32string */
std::is_same<CharT, wchar_t> /* std::wstring */
if (res == 0 || res == 1) {
value = (bool) res;
return true;
+ } else {
+ PyErr_Clear();
}
}
return false;
// Simplify life by being able to assume standard char sizes (the standard only guarantees
// minimums, but Python requires exact sizes)
static_assert(!std::is_same<CharT, char>::value || sizeof(CharT) == 1, "Unsupported char size != 1");
+#if defined(PYBIND11_HAS_U8STRING)
+ static_assert(!std::is_same<CharT, char8_t>::value || sizeof(CharT) == 1, "Unsupported char8_t size != 1");
+#endif
static_assert(!std::is_same<CharT, char16_t>::value || sizeof(CharT) == 2, "Unsupported char16_t size != 2");
static_assert(!std::is_same<CharT, char32_t>::value || sizeof(CharT) == 4, "Unsupported char32_t size != 4");
// wchar_t can be either 16 bits (Windows) or 32 (everywhere else)
#if PY_MAJOR_VERSION >= 3
return load_bytes(load_src);
#else
- if (sizeof(CharT) == 1) {
+ if (std::is_same<CharT, char>::value) {
return load_bytes(load_src);
}
// without any encoding/decoding attempt). For other C++ char sizes this is a no-op.
// which supports loading a unicode from a str, doesn't take this path.
template <typename C = CharT>
- bool load_bytes(enable_if_t<sizeof(C) == 1, handle> src) {
+ bool load_bytes(enable_if_t<std::is_same<C, char>::value, handle> src) {
if (PYBIND11_BYTES_CHECK(src.ptr())) {
// We were passed a Python 3 raw bytes; accept it into a std::string or char*
// without any encoding attempt.
}
template <typename C = CharT>
- bool load_bytes(enable_if_t<sizeof(C) != 1, handle>) { return false; }
+ bool load_bytes(enable_if_t<!std::is_same<C, char>::value, handle>) { return false; }
};
template <typename CharT, class Traits, class Allocator>
template <size_t... Is>
bool load_impl(const sequence &seq, bool convert, index_sequence<Is...>) {
+#ifdef __cpp_fold_expressions
+ if ((... || !std::get<Is>(subcasters).load(seq[Is], convert)))
+ return false;
+#else
for (bool r : {std::get<Is>(subcasters).load(seq[Is], convert)...})
if (!r)
return false;
+#endif
return true;
}
template <size_t... Is>
bool load_impl_sequence(function_call &call, index_sequence<Is...>) {
+#ifdef __cpp_fold_expressions
+ if ((... || !std::get<Is>(argcasters).load(call.args[Is], call.args_convert[Is])))
+ return false;
+#else
for (bool r : {std::get<Is>(argcasters).load(call.args[Is], call.args_convert[Is])...})
if (!r)
return false;
+#endif
return true;
}
template <typename Return, typename Func, size_t... Is, typename Guard>
- Return call_impl(Func &&f, index_sequence<Is...>, Guard &&) {
+ Return call_impl(Func &&f, index_sequence<Is...>, Guard &&) && {
return std::forward<Func>(f)(cast_op<Args>(std::move(std::get<Is>(argcasters)))...);
}