I am trying to implement some functional constructs in C ++. It is required to implement a function that aligns the list of lists with any number of levels down.
template<typename T, typename R> struct Fold{ typedef R(*func)(T, R); }; template<typename T> T head(std::list<T> const& list) { return list.front(); } template<typename T> std::list<T> tail(std::list<T> list) { list.pop_front(); return list; } template<typename T> std::list<T> cons(T head, std::list<T> tail){ tail.push_front(head); return tail; } template<typename T, typename ACCUM> ACCUM foldl(typename Fold<T, ACCUM>::func function, ACCUM accum, std::list<T> list) { if(list.empty()) return accum; return foldl(function, (*function)(head(list), accum), tail(list)); } template<typename T, typename ACCUM> ACCUM foldr(typename Fold<T, ACCUM>::func function, ACCUM accum, std::list<T> list) { if(list.empty()) return accum; return (*function)(head(list), foldr(function, accum, tail(list))); } template<typename T> std::list<T> reverse(std::list<T> list){ struct LAMBDA{ static std::list<T> reverse(T t, std::list<T> tList){ return cons(t, tList); } }; std::list<T> revTList; return foldl( static_cast<typename Fold<T, std::list<T>>::func>(&LAMBDA::reverse), revTList, list); } template<typename T> std::list<T> append(std::list<T> list1, std::list<T> list2) { struct LAMBDA{ static std::list<T> append_lambda(T t, std::list<T> list){ return cons(t, list);; } }; return foldl( static_cast<typename Fold<T, std::list<T>>::func>(&LAMBDA::append_lambda), list2, reverse(list1)); } template<typename T, typename Ty> struct Flattener{ static std::list<T> flatten(typename std::list<Ty> deepList){ struct LAMBDA{ static Ty flatten_lambda(Ty ty, Ty accum){ return append(ty, accum); } }; Ty ty; Ty flat = foldr( static_cast<typename Fold<Ty, Ty>::func>(&LAMBDA::flatten_lambda), ty, deepList); return Flattener::flatten(flat); } }; template<typename T> struct Flattener<T, T>{ static std::list<T> flatten(std::list<T> list){ return list; } };
The above code compiles fine, but when I try to call a function with
std::list<int> emptyList; std::list<int> list1 = cons(1, cons(2, cons(3, cons(4, emptyList)))); std::list<int> list2 = cons(5, cons(6, cons(7, cons(8, emptyList)))); std::list<std::list<int>> emptyDeepList; std::list<std::list<int>> deepList = cons(list1, cons(list2, emptyDeepList)); Flattener<int, std::list<int>>::flatten(deepList);
I get this huge error when compiling code:
error C2664: 'Flattener<T,Ty>::flatten' : cannot convert parameter 1 from 'std::list<T>' to 'std::list<T>' with [ T=int, Ty=std::list<int> ] and [ T=int ] and [ T=std::list<int> ] No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called list.h(212) : while compiling class template member function 'std::list<T> Flattener<T,Ty>::flatten(std::list<std::list<T>>)' with [ T=int, Ty=std::list<int> ] main.cpp(67) : see reference to class template instantiation 'Flattener<T,Ty>' being compiled with [ T=int, Ty=std::list<int> ]
If I remove the Flattener::flatten , the code compiles.
What am I doing wrong? (Since I am new to C ++ programming and template, some explanations will also be useful).
Edit:
Tried this one. The same mistake. I think I'm on something.
template<typename T, typename L> struct Flattener{ static std::list<T> flatten(L list){ struct LAMBDA{ static std::list<T> flatten_lambda(typename L1 l1, std::list<T> tList){ return append(Flattener<T, L1>::flatten(l1), tList); } }; std::list<T> tList; return foldl(&LAMBDA::flatten_lambda, tList, list); } }; template<typename T> struct Flattener<T, typename std::list<T>>{ static std::list<T> flatten(std::list<T> list){ return list; } };
And here is the compiler error for this:
error C2664: 'Flattener<T,L>::flatten' : cannot convert parameter 1 from 'std::list<T>' to 'std::list<T>' with [ T=int, L=std::list<std::list<int>> ] and [ T=std::list<std::list<int>> ] and [ T=std::list<int> ] No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called