【发布时间】:2015-10-17 22:04:12
【问题描述】:
我正在尝试在 C++ 中实现一些功能结构。想要实现一个功能,将列表列表展平任意数量的级别。
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;
}
};
上面的代码编译得很好,但是当我尝试用
调用函数时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);
编译代码时出现这个巨大的错误:
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>
]
如果我删除对Flattener::flatten 的调用,代码就会编译。
我做错了什么? (因为我是 C++ 和模板编程的新手,所以一些解释也会很有帮助)。
编辑:
试过这个。同样的错误。我想我在做某事。
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;
}
};
这是这个编译器的错误:
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
【问题讨论】:
-
不确定,但
Fold<Ty, Ty>::func需要typename,因为它是依赖的。 -
另外,
return Flattener::flatten(flat);是无限递归的(或者更确切地说,如果类型允许它编译,它将是无限递归的)。它没有拾取类的特化,因为这里的Flatten指的是它所使用的实例化。 -
第一个评论,我也是这么想的,但是编译没有报错,后来习惯了不写的习惯。切入正题,它仍然可以在不提及
typename的情况下使用。 -
第二条评论,我明白了,那么我该如何重做这个以实现我想做的事情。
-
你可以写
Flattener<A, B>::flatten,其中A和B是相关类型,可能是同一个类型?
标签: c++ templates visual-c++ functional-programming