Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions include/boost/lexical_cast/detail/converter_lexical_streams.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ namespace boost {

namespace boost { namespace detail { namespace lcast {

template <class C, class CharT>
using enable_if_compatible_char_t = typename std::enable_if<
std::is_same<const C, const CharT>::value || (
std::is_same<const char, const CharT>::value && (
std::is_same<const C, const unsigned char>::value ||
std::is_same<const C, const signed char>::value
)
), bool
>::type;

template <typename T>
struct exact {
static_assert(!std::is_const<T>::value, "");
Expand Down Expand Up @@ -256,16 +266,6 @@ namespace boost { namespace detail { namespace lcast {
}
#endif
public:
template <class C>
using enable_if_compatible_char_t = typename std::enable_if<
std::is_same<const C, const CharT>::value || (
std::is_same<const char, const CharT>::value && (
std::is_same<const C, const unsigned char>::value ||
std::is_same<const C, const signed char>::value
)
), bool
>::type;

template<class CharTraits, class Alloc>
bool stream_in(lcast::exact<std::basic_string<CharT,CharTraits,Alloc>> x) noexcept {
start = x.payload.data();
Expand Down Expand Up @@ -294,7 +294,7 @@ namespace boost { namespace detail { namespace lcast {
}

template <class C>
enable_if_compatible_char_t<C>
enable_if_compatible_char_t<C, CharT>
stream_in(lcast::exact<boost::iterator_range<C*>> x) noexcept {
auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end());
return stream_in(lcast::exact<decltype(buf)>{buf});
Expand All @@ -311,7 +311,7 @@ namespace boost { namespace detail { namespace lcast {
#endif

template <class Type>
enable_if_compatible_char_t<Type>
enable_if_compatible_char_t<Type, CharT>
stream_in(lcast::exact<Type*> x) { return shl_char_array(reinterpret_cast<CharT const*>(x.payload)); }

template <class Type>
Expand All @@ -334,28 +334,28 @@ namespace boost { namespace detail { namespace lcast {
}

template <class C, std::size_t N>
enable_if_compatible_char_t<C>
enable_if_compatible_char_t<C, CharT>
stream_in(lcast::exact<boost::array<C, N>> x) noexcept {
return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N);
}

template <class C, std::size_t N>
enable_if_compatible_char_t<C>
enable_if_compatible_char_t<C, CharT>
stream_in(lcast::exact<std::array<C, N>> x) noexcept {
return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N);
}

#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
template <class C, class CharTraits>
enable_if_compatible_char_t<C>
enable_if_compatible_char_t<C, CharT>
stream_in(lcast::exact<std::basic_string_view<C, CharTraits>> x) noexcept {
start = reinterpret_cast<const CharT*>(x.payload.data());
finish = start + x.payload.size();
return true;
}
#endif
template <class C, class CharTraits>
enable_if_compatible_char_t<C>
enable_if_compatible_char_t<C, CharT>
stream_in(lcast::exact<boost::basic_string_view<C, CharTraits>> x) noexcept {
start = reinterpret_cast<const CharT*>(x.payload.data());
finish = start + x.payload.size();
Expand Down Expand Up @@ -667,14 +667,14 @@ namespace boost { namespace detail { namespace lcast {
}

template <class C, std::size_t N>
bool stream_out(std::array<C, N>& output) noexcept {
static_assert(sizeof(C) == sizeof(CharT), "");
enable_if_compatible_char_t<C, CharT>
stream_out(std::array<C, N>& output) noexcept {
return shr_std_array<N>(output);
}

template <class C, std::size_t N>
bool stream_out(boost::array<C, N>& output) noexcept {
static_assert(sizeof(C) == sizeof(CharT), "");
enable_if_compatible_char_t<C, CharT>
stream_out(boost::array<C, N>& output) noexcept {
return shr_std_array<N>(output);
}

Expand Down
126 changes: 121 additions & 5 deletions test/arrays_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,101 @@ using namespace boost;
#define BOOST_LC_RUNU32
#endif

namespace user_namespace {

struct user_type {
char payload;
};

template <std::size_t Size>
inline std::ostream& operator<<(std::ostream& os, const boost::array<user_type, Size>& array) {
for (const auto& x : array) {
os << '@' << x.payload;
}
return os;
}

template <std::size_t Size>
inline std::ostream& operator<<(std::ostream& os, const std::array<user_type, Size>& array) {
for (const auto& x : array) {
os << '@' << x.payload;
}
return os;
}

template <std::size_t Size>
inline std::istream& operator>>(std::istream& is, boost::array<user_type, Size>& array) {
for (auto& x : array) {
char at{};
is >> at >> x.payload;
BOOST_TEST_EQ(at, '@');
}
return is;
}

template <std::size_t Size>
inline std::istream& operator>>(std::istream& is, std::array<user_type, Size>& array) {
for (auto& x : array) {
char at{};
is >> at >> x.payload;
}
return is;
}



struct another_user_type {
another_user_type()
: payload('\0')
, payload1('-')
{}

another_user_type(char in_payload, char in_payload1)
: payload(in_payload)
, payload1(in_payload1)
{}

char payload;
char payload1;
};

template <std::size_t Size>
inline std::ostream& operator<<(std::ostream& os, const boost::array<another_user_type, Size>& array) {
for (const auto& x : array) {
os << '@' << x.payload;
}
return os;
}

template <std::size_t Size>
inline std::ostream& operator<<(std::ostream& os, const std::array<another_user_type, Size>& array) {
for (const auto& x : array) {
os << '@' << x.payload;
}
return os;
}

template <std::size_t Size>
inline std::istream& operator>>(std::istream& is, boost::array<another_user_type, Size>& array) {
for (auto& x : array) {
char at{};
is >> at >> x.payload;
BOOST_TEST_EQ(at, '@');
}
return is;
}

template <std::size_t Size>
inline std::istream& operator>>(std::istream& is, std::array<another_user_type, Size>& array) {
for (auto& x : array) {
char at{};
is >> at >> x.payload;
}
return is;
}

}

template <template <class, std::size_t> class ArrayT, class T>
static void testing_template_array_output_on_spec_value(T val)
{
Expand All @@ -33,6 +128,8 @@ static void testing_template_array_output_on_spec_value(T val)
typedef ArrayT<unsigned char, 1> ushort_arr_type;
typedef ArrayT<signed char, 4> sarr_type;
typedef ArrayT<signed char, 3> sshort_arr_type;
typedef ArrayT<user_namespace::user_type, 2> user_arr_type;
typedef ArrayT<user_namespace::another_user_type, 2> another_user_arr_type;

std::string ethalon("100");
using namespace std;
Expand Down Expand Up @@ -61,6 +158,30 @@ static void testing_template_array_output_on_spec_value(T val)
BOOST_TEST_THROWS(lexical_cast<sshort_arr_type>(val), boost::bad_lexical_cast);
}

{
auto res1 = lexical_cast<std::string>(user_arr_type{
user_namespace::user_type{'a'},
user_namespace::user_type{'z'},
});
BOOST_TEST_EQ(res1, "@a@z");

auto res2 = lexical_cast<user_arr_type>("@b@y");
BOOST_TEST_EQ(res2[0].payload, 'b');
BOOST_TEST_EQ(res2[1].payload, 'y');
}

{
auto res1 = lexical_cast<std::string>(another_user_arr_type{
user_namespace::another_user_type('a', '-'),
user_namespace::another_user_type('z', '-'),
});
BOOST_TEST_EQ(res1, "@a@z");

auto res2 = lexical_cast<another_user_arr_type>("@b@y");
BOOST_TEST_EQ(res2[0].payload, 'b');
BOOST_TEST_EQ(res2[1].payload, 'y');
}

#if !defined(BOOST_NO_STRINGSTREAM) && !defined(BOOST_NO_STD_WSTRING) && !defined(_LIBCPP_VERSION)
typedef ArrayT<wchar_t, 300> warr_type;
typedef ArrayT<wchar_t, 3> wshort_arr_type;
Expand Down Expand Up @@ -249,13 +370,11 @@ void testing_boost_array_output_conversion()

void testing_std_array_output_conversion()
{
#ifndef BOOST_NO_CXX11_HDR_ARRAY
testing_template_array_output_on_char_value<std::array>();
testing_template_array_output_on_spec_value<std::array>(100);
testing_template_array_output_on_spec_value<std::array>(static_cast<short>(100));
testing_template_array_output_on_spec_value<std::array>(static_cast<unsigned short>(100));
testing_template_array_output_on_spec_value<std::array>(static_cast<unsigned int>(100));
#endif

BOOST_TEST(true);
}
Expand Down Expand Up @@ -354,10 +473,7 @@ void testing_boost_array_input_conversion()

void testing_std_array_input_conversion()
{
#ifndef BOOST_NO_CXX11_HDR_ARRAY
testing_generic_array_input_conversion<std::array>();
#endif

BOOST_TEST(true);
}

Expand Down
Loading