【发布时间】:2014-08-22 16:29:12
【问题描述】:
我来自 Haskell,目前正在修改 C++11,看看它能做什么。我的一个玩具是一个小模板,它试图模仿 Haskell map 函数,即它需要一个包含 X 值的容器和一个将 X 映射到 Y 的函数,并产生一个包含以下值的容器Y。我知道我可以使用std::transform 轻松做到这一点,但这会破坏乐趣。
现在,我的模板如下所示:
template <typename T, typename U>
void myMap( const T &input,
U &output,
std::function<typename U::value_type (typename T::value_type)> f );
现在,我的问题是:是否可以调整签名,而不是通过引用(第二个参数)获取输出容器,而是通过返回值生成一个新容器,但编译器可以推断返回类型?像
template <typename T, typename U>
U myMap( const T &input,
std::function<typename U::value_type (typename T::value_type)> f );
可惜不能这样称呼
std::vector<int> x = { 1, 2, 3, 4 };
std::list<bool> y = myMap( x, []( int x ) { return x % 2 == 0; } );
...至少 Clang 无法在这里推断出返回类型。
我的一个想法是,鉴于输入容器类型和函数类型是已知的,您可以从中构造输出类型。 IE。像
template <typename C, typename T, typename U>
C<U> myMap( const C<T> &input,
std::function<U (T)> f );
...但是唉C<U> 似乎甚至不是有效的语法。我想知道我是否只需要正确的decltype 仙尘,就像this question 中的情况一样。
【问题讨论】:
-
我记得我做了一些与您想要的类似的事情,除了它与
std::string的效果不太好,因为它是std::basic_string<T, U>,并且切换它会导致它像std::basic_string<int, T>这样的东西。但是,我有一个适用于其他一切的尝试。 -
auto y = map<std::list>(x, [](int x){...});可以接受吗?你不能在 C++ 中推断返回类型。 -
在 C++ 中,我们通常不直接使用容器,而是使用迭代器范围。 Haskell 和 C++ 不能很好地相互转换。对于每种语言,学习它的方式。
-
@n.m.:点了。我知道这并不完全是惯用的,我只是碰巧用它来强调 C++ 的(元)类型系统。 :-)
-
std::vector<int>::rebind<char>会很有趣......分配器会这样做,为什么不容器呢?