我来自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>
甚至似乎都不是有效的语法。我想知道是否像this question一样需要正确的decltype
仙尘。 最佳答案
您可能正在寻找这种语法
#include <algorithm>
#include <functional>
#include <type_traits>
#include <list>
template
<
template<typename, typename...> class Container,
typename InType,
typename FuncType,
typename... Rest
>
auto myMap (const Container<InType, Rest...>& container,
FuncType func) ->
Container<decltype(func(std::declval<InType>())), Rest...>
{
Container<decltype(func(std::declval<InType>())), Rest...> result;
std::transform(std::begin(container),
std::end(container),
std::back_inserter(result),
func);
return result;
}
尽管我不建议在任何实际项目中使用这种样式的代码。