Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
rollbear committed Dec 13, 2016
2 parents 5943fe8 + 99d28c3 commit 37bed54
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 10 deletions.
44 changes: 44 additions & 0 deletions compiling_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3033,6 +3033,50 @@ TEST_CASE_METHOD(Fixture, "unknown object is one line if 8 bytes", "[streaming]"
REQUIRE(os.str() == "8-byte object={ 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 }");
}

TEST_CASE_METHOD(Fixture, "A std::pair<> is printed as { val1, val2 }", "[streaming]")
{
std::ostringstream os;
trompeloeil::print(os, std::make_pair(3, std::string("hello")));
REQUIRE(os.str() == "{ 3, hello }");
}

TEST_CASE_METHOD(Fixture, "A std::tuple<> is printed as { val1, val2, val3, }", "[streaming]")
{
std::ostringstream os;
trompeloeil::print(os, std::make_tuple(3, "hello", std::string("world")));
REQUIRE(os.str() == "{ 3, hello, world }");
}

TEST_CASE_METHOD(Fixture, "A C-array is printed as { val1, val2, val3 }", "[streaming]")
{
std::ostringstream os;
std::tuple<int, std::string> v[] {
std::make_tuple(1, "one"),
std::make_tuple(2, "two"),
std::make_tuple(3, "three")
};
static_assert(!trompeloeil::is_output_streamable<decltype(v)>(),"");
static_assert(trompeloeil::is_collection<decltype(v)>(), "");
trompeloeil::print(os, v);
REQUIRE(os.str() == "{ { 1, one }, { 2, two }, { 3, three } }");
}

TEST_CASE_METHOD(Fixture, "A std::map<> is printed as { { key1, val1 }, { key2, val2 } }", "[streaming]")
{
std::ostringstream os;
std::map<std::string, int> m{ {"one", 1}, {"two", 2 }, {"three", 3 } };
trompeloeil::print(os, m);
REQUIRE(os.str() == "{ { one, 1 }, { three, 3 }, { two, 2 } }");
}

TEST_CASE_METHOD(Fixture, "A tuple with pairs and maps is printed element wise", "[streaming]")
{
std::ostringstream os;
auto v = std::make_tuple(std::make_pair(3, std::string("hello")),
std::map<int, std::string>{{1, "one"},{2, "two"},{3, "three"}});
trompeloeil::print(os, v);
REQUIRE(os.str() == "{ { 3, hello }, { { 1, one }, { 2, two }, { 3, three } } }");
}
namespace nn
{
struct TestOutput;
Expand Down
152 changes: 142 additions & 10 deletions trompeloeil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,17 @@ namespace trompeloeil
return {};
}

template <typename T, size_t N>
inline
constexpr
auto
is_output_streamable_(
T(*)[N])
-> std::false_type
{
return {};
}

template <typename T>
inline
constexpr
Expand Down Expand Up @@ -602,7 +613,62 @@ namespace trompeloeil
::trompeloeil::is_null_comparable<T>::value);
}

template <typename T, bool = is_output_streamable<T>()>
template <typename T, size_t N>
inline
constexpr
bool
is_null(
T(&)[N])
noexcept
{
return false;
}

template <typename T>
void
print(
std::ostream& os,
T const &t);

template <typename T>
constexpr
std::integral_constant<decltype(std::next(std::begin(std::declval<T>()))
!= std::end(std::declval<T>())),
true>
is_collection_(T*)
{
return {};
}

template <typename T>
constexpr
auto
is_collection_(...)
-> std::false_type
{
return {};
}

template <typename T, bool b = is_collection_<T>(nullptr)>
struct array_discriminator : std::true_type { };

template <typename T, size_t N>
struct array_discriminator<T[N], false> : std::true_type { };

template <typename T>
struct array_discriminator<T, false> : std::false_type { };

template <typename T>
constexpr
auto
is_collection()
{
return array_discriminator<T>{};
}

template <typename T,
bool = is_output_streamable<T>(),
bool = is_collection<std::remove_reference_t<T>>()>
struct streamer
{
static
Expand All @@ -616,9 +682,75 @@ namespace trompeloeil
}
};

template <typename ... T>
struct streamer<std::tuple<T...>, false, false>
{
static
void
print(
std::ostream& os,
std::tuple<T...> const& t)
{
print_tuple(os, t, std::index_sequence_for<T...>{});
}
template <size_t ... I>
static
void
print_tuple(
std::ostream& os,
std::tuple<T...> const& t,
std::index_sequence<I...>)
{
os << "{ ";
const char* sep = "";
std::initializer_list<const char*> v{((os << sep),
::trompeloeil::print(os, std::get<I>(t)),
(sep = ", "))...};
ignore(v);
os << " }";
}
};

template <typename T, typename U>
struct streamer<std::pair<T, U>, false, false>
{
static
void
print(
std::ostream& os,
std::pair<T, U> const& t)
{
os << "{ ";
::trompeloeil::print(os, t.first);
os << ", ";
::trompeloeil::print(os, t.second);
os << " }";
}
};

template <typename T>
struct streamer<T, false, true>
{
static
void
print(
std::ostream& os,
T const& t)
{
os << "{ ";
const char* sep = "";
for (auto& elem : t)
{
os << sep;
::trompeloeil::print(os, elem);
sep = ", ";
}
os << " }";
}
};

template <typename T>
struct streamer<T, false>
struct streamer<T, false, false>
{
static
void
Expand Down Expand Up @@ -1264,10 +1396,10 @@ namespace trompeloeil
return Predicate::operator()(std::forward<V>(v), std::get<I>(value)...);
}
template <size_t ... I>
std::ostream& print_(std::ostream& os, std::index_sequence<I...>) const
std::ostream& print_(std::ostream& os_, std::index_sequence<I...>) const
{
Printer::operator()(os, std::get<I>(value)...);
return os;
Printer::operator()(os_, std::get<I>(value)...);
return os_;
}
std::tuple<T...> value;
};
Expand Down Expand Up @@ -2906,12 +3038,12 @@ namespace trompeloeil
call_modifier<M, Tag, Info>&& t)
const
{
using T = call_modifier<M, Tag, Info>;
using sigret = return_of_t<typename T::signature>;
using ret = typename T::return_type;
using call = call_modifier<M, Tag, Info>;
using sigret = return_of_t<typename call::signature>;
using ret = typename call::return_type;
constexpr bool retmatch = std::is_same<ret, sigret>::value;
constexpr bool forbidden = T::upper_call_limit == 0ULL;
constexpr bool valid_return_type = T::throws || retmatch || forbidden;
constexpr bool forbidden = call::upper_call_limit == 0ULL;
constexpr bool valid_return_type = call::throws || retmatch || forbidden;
static_assert(valid_return_type, "RETURN missing for non-void function");
auto tag = std::integral_constant<bool, valid_return_type>{};
return make_expectation(tag, std::move(t));
Expand Down

0 comments on commit 37bed54

Please sign in to comment.