如何让编译器推导出模板的返回类型? [英] How can I let the compiler deduce the return type of a template?

查看:131
本文介绍了如何让编译器推导出模板的返回类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我来自Haskell,目前正在修改C ++ 11,看看它能做什么。我的一个玩具是一个小模板,试图模仿Haskell map 函数,即它需要一个容器 X 和将 X 映射到 Y 并生成 Y 。我知道我可以很容易地使用 std :: transform ,但这将破坏乐趣。



右现在,我的模板看起来像这样:

 模板< typename T,typename U> 
void myMap(const T& input,
U& output,
std :: function< typename U :: value_type(typename T :: value_type)> f);

现在,我的问题是:是否可以调整签名,通过引用(第二个参数)我通过返回值产生一个新的容器,但编译器可以推导出返回类型?类似

 模板< 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无法在这里推导出返回类型。



我的一个想法是,鉴于输入容器类型和函数类型是已知的,你可以从中构造输出类型。也就是说例如

 模板< typename C,typename T,typename U> 
C< U> myMap(const C< T& input,
std :: function< U(T)> f);

... alas C< U> 甚至似乎不是有效的语法。我不知道我是否需要正确的 decltype 童话尘埃,如

您可能正在寻找此语法



  #include< algorithm& 
#include< functional>
#include< type_traits>
#include< list>

模板
<
template< typename,typename ...> class Container,
typename InType,
typename FuncType,
typename ... Rest
>
auto myMap(const Container FuncType func) - >
Container< decltype(func(std :: declval< InType>())),Rest ...>
{
Container< decltype(func(std :: declval< InType>())),Rest ...>结果;
std :: transform(std :: begin(container),
std :: end(container),
std :: back_inserter(result),
func);
return result;
}

虽然我不建议在任何真正的项目中使用这种风格的代码。 / p>

I'm coming from Haskell and currently tinker with C++11 to see what it can do. One of my toys is a small template which attempts to imitate the Haskell map function, i.e. it takes a container of values of X and a function mapping an X to a Y and yields a container of values of Y. I know that I could easily do that using std::transform, but that would spoil the fun.

Right now, my template looks like this:

template <typename T, typename U>
void myMap( const T &input,
            U &output,
            std::function<typename U::value_type (typename T::value_type)> f );

Now, my qustion is: is it possible to adjust the signature so that instead of taking the output container by reference (the second argument) I yield a new container via the return value and yet the compiler can deduce the return type? Something like

template <typename T, typename U>
U myMap( const T &input,
       std::function<typename U::value_type (typename T::value_type)> f );

unfortunately cannot be called like

std::vector<int> x = { 1, 2, 3, 4 };
std::list<bool> y = myMap( x, []( int x ) { return x % 2 == 0; } );

...at least Clang fails to deduce the return type here.

One idea I had was that given that the input container type and the function type is known, you could construct the output type from that. I.e. something like

template <typename C, typename T, typename U>
C<U> myMap( const C<T> &input,
            std::function<U (T)> f );

...but alas C<U> doesn't even seem to be valid syntax. I wonder if I just need the right decltype fairy dust as was the case in this question.

解决方案

You are probably looking for this syntax

#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;
}

though I would not recommend using this style of code in any real project.

这篇关于如何让编译器推导出模板的返回类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆