summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2021-02-13 12:47:39 +0100
committerRoland Reichwein <mail@reichwein.it>2021-02-13 12:47:39 +0100
commit07c77b45ba9f74cfe1bed547bea1eeb705f0582b (patch)
treedde45e92f704229c3ecc129aa2842686f052db6f
parent24ec1d5ba85503599fd301aa8cd56ee65651ab0b (diff)
Support G++, support string type as template argument for convert()
-rw-r--r--Makefile14
-rw-r--r--include/unicode.h21
-rw-r--r--src/test-unicode.cpp5
3 files changed, 28 insertions, 12 deletions
diff --git a/Makefile b/Makefile
index 7ea075e..39dcafb 100644
--- a/Makefile
+++ b/Makefile
@@ -5,16 +5,15 @@ DISTROS=base debian10 ubuntu2004 ubuntu2010
ifeq ($(wildcard $(shell which clang++-11)),)
ifeq ($(wildcard $(shell which clang++)),)
-$(error No clang++-11 nor clang++ available!)
+CXX=g++-10
else
CXX=clang++
endif
else
CXX=clang++-11
-# GCC is buggy: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282
-#CXX=g++-10
endif
+# boost is buggy for C++20: error: static_assert failed due to requirement 'detail::is_endian_reversible_inplace<char8_t>
STANDARD=c++17
#STANDARD=c++20
@@ -35,11 +34,6 @@ COMPILER_SUITE=clang
LIBS+=-fuse-ld=lld
endif
-ifeq ($(COMPILER_SUITE),clang)
-# libc++ is buggy for C++20: std::hash<char8_t> not implemented. Fixed in LLVM-12
-CXXFLAGS+=-stdlib=libc++
-endif
-
LDLIBS+=\
-lboost_context \
-lboost_filesystem \
@@ -47,6 +41,8 @@ LDLIBS+=\
-lboost_system \
ifeq ($(COMPILER_SUITE),clang)
+# libc++ is buggy for C++20: std::hash<char8_t> not implemented. Fixed in LLVM-12
+CXXFLAGS+=-stdlib=libc++
LIBS+= \
-lc++ \
-lc++abi
@@ -55,7 +51,7 @@ LIBS+= \
#-lstdc++fs
else
LIBS+= \
--lstdc++
+-lstdc++ \
-lstdc++fs
endif
diff --git a/include/unicode.h b/include/unicode.h
index d6f8e51..171496e 100644
--- a/include/unicode.h
+++ b/include/unicode.h
@@ -12,6 +12,7 @@
#include <memory>
#include <stdexcept>
#include <string>
+#include <type_traits>
#include <unordered_map>
#ifdef __cpp_char8_t
@@ -526,7 +527,7 @@ namespace unicode {
typedef UTF<utf_iterator<char32_t>, utf_back_insert_iterator<char32_t>> UTF_32;
// From and To are facets
- template<typename From, typename To>
+ template<typename From, typename To, std::enable_if_t<std::is_empty<From>::value && std::is_empty<To>::value, bool> = true>
std::basic_string<typename To::value_type> convert(const std::basic_string<typename From::value_type>& s)
{
std::basic_string<typename To::value_type> result;
@@ -561,7 +562,9 @@ namespace unicode {
};
// From and To are from: utf8_t, char16_t and char32_t
- template<typename From, typename To>
+ template<typename From, typename To,
+ std::enable_if_t<std::is_trivial<From>::value && std::is_trivial<To>::value, bool> = true
+ >
std::basic_string<To> convert(const std::basic_string<From>& s)
{
typedef UTF<utf_iterator<From>, utf_back_insert_iterator<To>> UTF_Trait;
@@ -573,6 +576,20 @@ namespace unicode {
return result;
}
+ template<typename FromContainer, typename ToContainer,
+ std::enable_if_t<!std::is_empty<FromContainer>::value && !std::is_empty<ToContainer>::value, bool> = true
+ >
+ ToContainer convert(const FromContainer& s)
+ {
+ typedef UTF<utf_iterator<typename FromContainer::value_type>, utf_back_insert_iterator<typename ToContainer::value_type>> UTF_Trait;
+
+ ToContainer result;
+
+ std::copy(UTF_Trait::begin(s), UTF_Trait::end(s), UTF_Trait::back_inserter(result));
+
+ return result;
+ }
+
// basic type version
template<typename T>
bool is_valid_utf(const std::basic_string<T>& s)
diff --git a/src/test-unicode.cpp b/src/test-unicode.cpp
index 99a8f99..5f5ebbf 100644
--- a/src/test-unicode.cpp
+++ b/src/test-unicode.cpp
@@ -351,6 +351,10 @@ BOOST_AUTO_TEST_CASE(convert)
BOOST_CHECK((unicode::convert<char, wchar_t>(u8"\U0001F63A")) == std::wstring{L"\U0001F63A"});
BOOST_CHECK((unicode::convert<wchar_t, char32_t>(L"\U0001F63A")) == std::u32string{U"\U0001F63A"});
BOOST_CHECK((unicode::convert<wchar_t, char>(L"\U0001F63A")) == std::string{u8"\U0001F63A"});
+
+ BOOST_CHECK((unicode::convert<std::string, std::wstring>(std::string{"äöü"})) == std::wstring{L"äöü"});
+
+ //BOOST_CHECK((unicode::convert<std::vector<char>, std::vector<wchar_t>>(std::vector<char>{})) == std::vector<wchar_t>{});
}
BOOST_AUTO_TEST_CASE(is_valid_utf)
@@ -375,6 +379,5 @@ BOOST_AUTO_TEST_CASE(string_u8string)
// TODO:
//
-// char8_t, char16_t, char32_t, char, wchar_t (UTF-16 on Windows, UTF-32 on Linux)
// string, vector?
// uint8_t, uint16_t, uint32_t?