Fix collection printing for pairs, recursion, and std::vector<bool>.
This commit is contained in:
parent
7ab0d2ca97
commit
165e7ea0b5
@ -124,87 +124,80 @@ namespace cling {
|
||||
|
||||
// Collections internal
|
||||
namespace collectionPrinterInternal {
|
||||
// Maps
|
||||
template<typename Pair>
|
||||
std::string printPair(const Pair& P) {
|
||||
return printValue(&P->first) + " => " + printValue(&P->second);
|
||||
}
|
||||
|
||||
template<typename CollectionType>
|
||||
auto printValue_impl(const CollectionType *obj, short)
|
||||
-> decltype(
|
||||
++(obj->begin()), obj->end(),
|
||||
obj->begin()->first, obj->begin()->second,
|
||||
std::string())
|
||||
{
|
||||
auto iter = obj->begin();
|
||||
auto iterEnd = obj->end();
|
||||
if (iter == iterEnd)
|
||||
return valuePrinterInternal::kEmptyCollection;
|
||||
|
||||
std::string str("{ ");
|
||||
str += printPair(iter);
|
||||
while (++iter != iterEnd) {
|
||||
str += ", ";
|
||||
str += printPair(iter);
|
||||
}
|
||||
return str + " }";
|
||||
// Forward declaration, so recursion of containers possible.
|
||||
template <typename T> std::string printValue(const T* V, const void* = 0);
|
||||
|
||||
template <typename T> std::string
|
||||
printValue(const T& V, typename std::enable_if<
|
||||
std::is_pointer<decltype(&V)>::value>::type* = 0) {
|
||||
return printValue(&V);
|
||||
}
|
||||
|
||||
// Vector, set, deque etc.
|
||||
template<typename CollectionType>
|
||||
auto printValue_impl(const CollectionType *obj, int)
|
||||
-> decltype(
|
||||
++(obj->begin()), obj->end(),
|
||||
*(obj->begin()), &(*(obj->begin())),
|
||||
std::string())
|
||||
{
|
||||
auto iter = obj->begin();
|
||||
auto iterEnd = obj->end();
|
||||
if (iter == iterEnd)
|
||||
return valuePrinterInternal::kEmptyCollection;
|
||||
template <typename T0, typename T1> std::string
|
||||
printValue(const std::pair<T1, T0>* V, const void* AsMap = 0) {
|
||||
if (AsMap)
|
||||
return printValue(&V->first) + " => " + printValue(&V->second);
|
||||
return "{" + printValue(&V->first) + " , " + printValue(&V->second) + "}";
|
||||
}
|
||||
|
||||
// For std::vector<bool> elements
|
||||
std::string printValue(const bool& B, const void* = 0) {
|
||||
return cling::printValue(&B);
|
||||
}
|
||||
|
||||
struct TypeTest {
|
||||
template <class T> static constexpr const void*
|
||||
isMap(const T* M, const typename T::mapped_type* V = 0) { return M; }
|
||||
static constexpr const void* isMap(const void* M) { return nullptr; }
|
||||
};
|
||||
|
||||
// vector, set, deque etc.
|
||||
template <typename CollectionType>
|
||||
auto printValue_impl(
|
||||
const CollectionType* obj,
|
||||
typename std::enable_if<
|
||||
std::is_reference<decltype(*(obj->begin()))>::value>::type* = 0)
|
||||
-> decltype(++(obj->begin()), obj->end(), std::string()) {
|
||||
auto iter = obj->begin(), iterEnd = obj->end();
|
||||
if (iter == iterEnd) return valuePrinterInternal::kEmptyCollection;
|
||||
|
||||
const void* M = TypeTest::isMap(obj);
|
||||
|
||||
std::string str("{ ");
|
||||
str += printValue(&(*iter));
|
||||
str += printValue(&(*iter), M);
|
||||
while (++iter != iterEnd) {
|
||||
str += ", ";
|
||||
str += printValue(&(*iter));
|
||||
str += printValue(&(*iter), M);
|
||||
}
|
||||
return str + " }";
|
||||
}
|
||||
|
||||
// As above, but without ability to take address of elements.
|
||||
template<typename CollectionType>
|
||||
auto printValue_impl(const CollectionType *obj, long)
|
||||
-> decltype(
|
||||
++(obj->begin()), obj->end(),
|
||||
*(obj->begin()),
|
||||
std::string())
|
||||
{
|
||||
auto iter = obj->begin();
|
||||
auto iterEnd = obj->end();
|
||||
if (iter == iterEnd)
|
||||
return valuePrinterInternal::kEmptyCollection;
|
||||
template <typename CollectionType>
|
||||
auto printValue_impl(
|
||||
const CollectionType* obj,
|
||||
typename std::enable_if<
|
||||
!std::is_reference<decltype(*(obj->begin()))>::value>::type* = 0)
|
||||
-> decltype(++(obj->begin()), obj->end(), std::string()) {
|
||||
auto iter = obj->begin(), iterEnd = obj->end();
|
||||
if (iter == iterEnd) return valuePrinterInternal::kEmptyCollection;
|
||||
|
||||
std::string str("{ ");
|
||||
const auto value0 = (*iter);
|
||||
str += printValue(&value0);
|
||||
str += printValue(*iter);
|
||||
while (++iter != iterEnd) {
|
||||
const auto valueN = (*iter);
|
||||
str += ", ";
|
||||
str += printValue(&valueN);
|
||||
str += printValue(*iter);
|
||||
}
|
||||
return str + " }";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collections
|
||||
template<typename CollectionType>
|
||||
auto printValue(const CollectionType *obj)
|
||||
-> decltype(collectionPrinterInternal::printValue_impl(obj, 0), std::string())
|
||||
{
|
||||
// short -> int -> long = priority order
|
||||
return collectionPrinterInternal::printValue_impl(obj, (short)0);
|
||||
-> decltype(collectionPrinterInternal::printValue_impl(obj), std::string()) {
|
||||
return collectionPrinterInternal::printValue_impl(obj);
|
||||
}
|
||||
|
||||
// Arrays
|
||||
@ -298,6 +291,13 @@ namespace cling {
|
||||
using T = std::pair<ARGS...>;
|
||||
return collectionPrinterInternal::tuplePairPrintValue<T>(val);
|
||||
}
|
||||
|
||||
namespace collectionPrinterInternal {
|
||||
// Keep this last to allow picking up all specializations above.
|
||||
template <typename T> std::string printValue(const T* V, const void*) {
|
||||
return cling::printValue(V);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -13,11 +13,20 @@
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
std::vector<bool> Bv(5,5)
|
||||
// FIXME: Printing std::vector<bool> is still broken.
|
||||
// But the line above at least tests cling doesn't crash because of it.
|
||||
// BROKENCHECK: (std::vector<bool> &) { true, true, true, true, true }
|
||||
// CHECK: (std::vector<bool> &) { true, true, true, true, true }
|
||||
|
||||
std::vector<std::vector<bool>> Bvv;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
Bvv.push_back(std::vector<bool>());
|
||||
for (int j = 0, N = i+1; j < N; ++j)
|
||||
Bvv.back().push_back(j % 4);
|
||||
}
|
||||
Bvv.push_back(std::vector<bool>());
|
||||
Bvv
|
||||
// CHECK-NEXT: (std::vector<std::vector<bool> > &) { { false }, { false, true }, { false, true, true }, { false, true, true, true }, { false, true, true, true, false }, {} }
|
||||
|
||||
class CustomThing {
|
||||
};
|
||||
@ -30,19 +39,45 @@ namespace cling {
|
||||
|
||||
std::vector<CustomThing> A, B(1);
|
||||
cling::printValue(&A) == cling::printValue(&B)
|
||||
// CHECK: (bool) false
|
||||
// CHECK-NEXT: (bool) false
|
||||
|
||||
std::tuple<> tA
|
||||
// CHECK: (std::tuple<> &) {}
|
||||
// CHECK-NEXT: (std::tuple<> &) {}
|
||||
|
||||
std::map<int, int> m
|
||||
// CHECK: (std::map<int, int> &) {}
|
||||
std::map<int, int> M
|
||||
// CHECK-NEXT: (std::map<int, int> &) {}
|
||||
std::map<int, std::pair<int,int> > M2;
|
||||
std::map<std::pair<std::string,bool>, std::pair<int,bool> > M3;
|
||||
std::set<std::pair<int, std::string>> S;
|
||||
std::map<std::string, std::map<int, std::pair<int,std::string>>> MM;
|
||||
|
||||
for (int i = 0; i < 5; ++i) m[i] = i+1;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
const std::string Str = std::to_string(i);
|
||||
M[i] = i+1;
|
||||
M2[i] = std::make_pair(i+1, i+2);
|
||||
M3[std::make_pair(Str, i%2)] = std::make_pair(i*10, i%3);
|
||||
S.insert(std::make_pair(i*10+4, Str));
|
||||
|
||||
m
|
||||
// CHECK: (std::map<int, int> &) { 0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5 }
|
||||
auto &MMv = MM[Str];
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
MMv[j] = std::make_pair(j*3, Str + std::to_string(j*5));
|
||||
}
|
||||
}
|
||||
|
||||
M
|
||||
// CHECK-NEXT: (std::map<int, int> &) { 0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5 }
|
||||
|
||||
M2
|
||||
// CHECK-NEXT: (std::map<int, std::pair<int, int> > &) { 0 => {1 , 2}, 1 => {2 , 3}, 2 => {3 , 4}, 3 => {4 , 5}, 4 => {5 , 6} }
|
||||
|
||||
M3
|
||||
// CHECK-NEXT: (std::map<std::pair<std::string, bool>, std::pair<int, bool> > &) { {"0" , false} => {0 , false}, {"1" , true} => {10 , true}, {"2" , false} => {20 , true}, {"3" , true} => {30 , false}, {"4" , false} => {40 , true} }
|
||||
|
||||
S
|
||||
// CHECK-NEXT: (std::set<std::pair<int, std::string> > &) { {4 , "0"}, {14 , "1"}, {24 , "2"}, {34 , "3"}, {44 , "4"} }
|
||||
|
||||
MM
|
||||
// (std::map<std::string, std::map<int, std::pair<int, std::string> > > &) { "0" => { 0 => {0 , "00"}, 1 => {3 , "05"}, 2 => {6 , "010"} }, "1" => { 0 => {0 , "10"}, 1 => {3 , "15"}, 2 => {6 , "110"} }, "2" => { 0 => {0 , "20"}, 1 => {3 , "25"}, 2 => {6 , "210"} }, "3" => { 0 => {0 , "30"}, 1 => {3 , "35"}, 2 => {6 , "310"} }, "4" => { 0 => {0 , "40"}, 1 => {3 , "45"}, 2 => {6 , "410"} } }
|
||||
|
||||
// expected-no-diagnostics
|
||||
.q
|
||||
|
Loading…
x
Reference in New Issue
Block a user