From ed7d1a6f43c3499aec7046837422c934149c2bfc Mon Sep 17 00:00:00 2001 From: klaus triendl Date: Tue, 7 Mar 2023 12:00:28 +0000 Subject: [PATCH 1/2] Detected the absence of string_view's iterator range ctor differently. There are environments that don't support the iterator constructor of string_view yet. E.g. macos and XCode 14.2 ship with libc++ 14, yet XCode picks up libc++ 13 installed on the system. --- dev/serializing_util.h | 20 +++++++++++------ include/sqlite_orm/sqlite_orm.h | 38 +++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/dev/serializing_util.h b/dev/serializing_util.h index 125cd666c..d568226c8 100644 --- a/dev/serializing_util.h +++ b/dev/serializing_util.h @@ -6,12 +6,12 @@ #include #include #include // std::exchange, std::tuple_size -#if __cplusplus >= 202002L && __cpp_lib_concepts +#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED #include #include // std::find #endif -#include "functional/cxx_universal.h" +#include "functional/cxx_universal.h" // ::size_t #include "functional/cxx_type_traits_polyfill.h" #include "tuple_helper/tuple_iteration.h" #include "error_code.h" @@ -29,9 +29,14 @@ namespace sqlite_orm { template std::string serialize_order_by(const T& t, const Ctx& context); -#if __cplusplus >= 202002L && \ - __cpp_lib_concepts // contiguous iterator ranges depend on contiguous_iterator, sized_sentinel_for in all major implementations - inline void stream_sql_escaped(std::ostream& os, const std::string& str, char char2Escape) { +#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED + // optimized version when string_view's iterator range constructor is available + template + void stream_sql_escaped(std::ostream& os, const std::string& str, char char2Escape) + requires requires { + std::string_view{str.cbegin(), str.cend()}; + } + { for(std::string::const_iterator it = str.cbegin(), next; true; it = next + 1) { next = std::find(it, str.cend(), char2Escape); os << std::string_view{it, next}; @@ -42,7 +47,9 @@ namespace sqlite_orm { os << std::string(2, char2Escape); } } -#else + + template +#endif inline void stream_sql_escaped(std::ostream& os, const std::string& str, char char2Escape) { if(str.find(char2Escape) == str.npos) { os << str; @@ -55,7 +62,6 @@ namespace sqlite_orm { } } } -#endif inline void stream_identifier(std::ostream& ss, const std::string& qualifier, diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 547f4cbd1..fd87913f2 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -13191,13 +13191,13 @@ namespace sqlite_orm { #include #include #include // std::exchange, std::tuple_size -#if __cplusplus >= 202002L && __cpp_lib_concepts +#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED #include #include // std::find #endif // #include "functional/cxx_universal.h" - +// ::size_t // #include "functional/cxx_type_traits_polyfill.h" // #include "tuple_helper/tuple_iteration.h" @@ -13219,9 +13219,14 @@ namespace sqlite_orm { template std::string serialize_order_by(const T& t, const Ctx& context); -#if __cplusplus >= 202002L && \ - __cpp_lib_concepts // contiguous iterator ranges depend on contiguous_iterator, sized_sentinel_for in all major implementations - inline void stream_sql_escaped(std::ostream& os, const std::string& str, char char2Escape) { +#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED + // optimized version when string_view's iterator range constructor is available + template + void stream_sql_escaped(std::ostream& os, const std::string& str, char char2Escape) + requires requires { + std::string_view{str.cbegin(), str.cend()}; + } + { for(std::string::const_iterator it = str.cbegin(), next; true; it = next + 1) { next = std::find(it, str.cend(), char2Escape); os << std::string_view{it, next}; @@ -13232,20 +13237,21 @@ namespace sqlite_orm { os << std::string(2, char2Escape); } } -#else - inline void stream_sql_escaped(std::ostream& os, const std::string& str, char char2Escape) { - if(str.find(char2Escape) == str.npos) { - os << str; - } else { - for(char c: str) { - if(c == char2Escape) { - os << char2Escape; - } - os << c; + + template +#endif + inline void stream_sql_escaped(std::ostream& os, const std::string& str, char char2Escape) { + if(str.find(char2Escape) == str.npos) { + os << str; + } else { + for(char c: str) { + if(c == char2Escape) { + os << char2Escape; } + os << c; } } -#endif + } inline void stream_identifier(std::ostream& ss, const std::string& qualifier, From d099e60d34b5008e54ed31af0714f1eda926904a Mon Sep 17 00:00:00 2001 From: klaus triendl Date: Tue, 7 Mar 2023 21:50:07 +0000 Subject: [PATCH 2/2] Addressed Clang 10 choking on concepts using non-template parameters --- dev/functional/cxx_compiler_quirks.h | 7 +++++++ dev/serializing_util.h | 4 ++-- include/sqlite_orm/sqlite_orm.h | 11 +++++++++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/dev/functional/cxx_compiler_quirks.h b/dev/functional/cxx_compiler_quirks.h index 6fcde5084..64e8ad78f 100644 --- a/dev/functional/cxx_compiler_quirks.h +++ b/dev/functional/cxx_compiler_quirks.h @@ -39,3 +39,10 @@ (defined(__clang__) && (__clang_major__ >= 12) && (__cplusplus >= 202002L)) #define SQLITE_ORM_CLASSTYPE_TEMPLATE_ARGS_SUPPORTED #endif + +// clang 10 chokes on concepts that don't depend on template parameters; +// when it tries to instantiate an expression in a requires expression, which results in an error, +// the compiler reports an error instead of dismissing the templated function. +#if defined(SQLITE_ORM_CONCEPTS_SUPPORTED) && (defined(__clang__) && (__clang_major__ == 10)) +#define SQLITE_ORM_BROKEN_NONTEMPLATE_CONCEPTS +#endif diff --git a/dev/serializing_util.h b/dev/serializing_util.h index d568226c8..fb1d696a0 100644 --- a/dev/serializing_util.h +++ b/dev/serializing_util.h @@ -6,7 +6,7 @@ #include #include #include // std::exchange, std::tuple_size -#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED +#if defined(SQLITE_ORM_CONCEPTS_SUPPORTED) && !defined(SQLITE_ORM_BROKEN_NONTEMPLATE_CONCEPTS) #include #include // std::find #endif @@ -29,7 +29,7 @@ namespace sqlite_orm { template std::string serialize_order_by(const T& t, const Ctx& context); -#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED +#if defined(SQLITE_ORM_CONCEPTS_SUPPORTED) && !defined(SQLITE_ORM_BROKEN_NONTEMPLATE_CONCEPTS) // optimized version when string_view's iterator range constructor is available template void stream_sql_escaped(std::ostream& os, const std::string& str, char char2Escape) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index fd87913f2..750c202d7 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -140,6 +140,13 @@ using std::nullptr_t; #define SQLITE_ORM_CLASSTYPE_TEMPLATE_ARGS_SUPPORTED #endif +// clang 10 chokes on concepts that don't depend on template parameters; +// when it tries to instantiate an expression in a requires expression, which results in an error, +// the compiler reports an error instead of dismissing the templated function. +#if defined(SQLITE_ORM_CONCEPTS_SUPPORTED) && (defined(__clang__) && (__clang_major__ == 10)) +#define SQLITE_ORM_BROKEN_NONTEMPLATE_CONCEPTS +#endif + #if SQLITE_ORM_HAS_INCLUDE() #include #endif @@ -13191,7 +13198,7 @@ namespace sqlite_orm { #include #include #include // std::exchange, std::tuple_size -#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED +#if defined(SQLITE_ORM_CONCEPTS_SUPPORTED) && !defined(SQLITE_ORM_BROKEN_NONTEMPLATE_CONCEPTS) #include #include // std::find #endif @@ -13219,7 +13226,7 @@ namespace sqlite_orm { template std::string serialize_order_by(const T& t, const Ctx& context); -#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED +#if defined(SQLITE_ORM_CONCEPTS_SUPPORTED) && !defined(SQLITE_ORM_BROKEN_NONTEMPLATE_CONCEPTS) // optimized version when string_view's iterator range constructor is available template void stream_sql_escaped(std::ostream& os, const std::string& str, char char2Escape)