【发布时间】:2018-04-10 06:30:50
【问题描述】:
我正在尝试用 C++ 开发一个 constexpr 函数式列表数据结构。我也在尝试利用 cons list 方法的递归结构。我有几次尝试,对于那些,你可以看到我过去的问题。现在,我已经决定让尺寸成为字体的一部分,即。 `名单。这是代码:
#include <iostream>
#include <type_traits>
template <typename T, unsigned int N>
struct list {
public:
constexpr list(const T& head, const list<T, N-1> &tail)
:_length{N}, _head{head}, _tail{tail}
{}
const unsigned int _length;
const T _head;
const list<T, N-1> _tail;
};
template <typename T, unsigned int N>
constexpr auto head(const list<T, N> &li) {
return li._head;
}
template <typename T, unsigned int N>
constexpr auto tail(const list<T, N> &li) {
return li._tail;
}
template <typename T, unsigned int N>
constexpr auto prepend(const T &new_head, const list<T, N> &li){
return list<T, N + 1>{new_head,
list<T, N>{head(li), tail(li)}};
}
template <typename T>
struct list<T, 0>
{
constexpr static const bool nil = true;
};
template <typename T>
using nil = list<T, 0>;
template <typename Functor, typename T, unsigned int N>
constexpr auto fmap(Functor f, const list<T, N> &li) {
if constexpr(N == 0)
return nil<T>{};
else
return list{f(head(li)), fmap(f, tail(li))};
}
template <typename T, unsigned int N>
std::ostream& operator<<(std::ostream& str, const list<T, N> &li) {
if constexpr(N == 0)
return str;
else{
str << head(li) << ' ' << tail(li);
return str;
}
}
int main(){
constexpr auto f = [](int x){ return x * x; };
constexpr list<char, 2> p2{'U', list<char, 1>{'S', nil<char>{}}};
constexpr auto p3 = prepend('S', p2);
constexpr list<int, 2> i1{1, list<int, 1>{2, nil<int>{}}};
constexpr auto i2 = fmap(f, i1);
std::cout << p3;
}
其中一些在某种程度上有效。 fmap 是阻止我的程序编译的那个。我得到了错误
prog.cc:47:16: 错误:没有可行的构造函数或推导指南来推导“列表”的模板参数 返回列表{f(head(li)), fmap(f, tail(li))};
prog.cc:47:34: 注意:在函数模板特化 'fmap' 的实例化中请求这里 返回列表{f(head(li)), fmap(f, tail(li))};
prog.cc:67:25:注意:在此处请求的函数模板特化 'fmap' 的实例化 constexpr auto i2 = fmap(f, i1);
prog.cc:8:15:注意:候选模板被忽略:无法推断模板参数“N” constexpr list(const T& head, const list &tail)
和类似的。我在这里迷路了,这个错误的原因是什么?似乎编译器正确地推断出参数N,正如它所说的N=2。我觉得我需要添加一些与大小为零的列表相关的基本案例,但无法弄清楚。
【问题讨论】:
-
不应该是
return list<T, N>{ f(head(li)), fmap(f, tail(li)) }吗? -
在函数
prepend()中你为什么不简单地返回list<T, N + 1>{new_head, li}?我错过了什么? -
@MariusBancila 考虑到
list甚至更奇怪@ 缺少 move-ctor。 -
你为什么需要
_length,它是模板参数。 -
@MariusBancila 抱歉,这是过去实施的一个错误,我忘了在那里进行更改。对于_length,我认为只是习惯性的。是的,我可以删除它。