2016-02-11 53 views
1

我用auto来存储就在自动分配构建一个lambda,但今天我看着this interesting paper on functional programming using c++ templates和跨越这些代码来:使用自动为定义的函数

template < typename T , typename Ops > 
T fold (Linked <T > * p) 
{ 
    T acc = Ops :: initial() ; 
    while (p) { 
    acc = Ops :: bin (acc , p - > head) ; 
    p = p - > tail ; 
    } 
    return acc ; 
} 

// later, in main(): 

auto sumup = fold <int , IntOps >; 

我想了解sumup的类型是什么,因为它不是分配给fold的输出,而是分配给实际功能fold本身!我决定看看auto显示使用的各种方式here。我假设这个auto的使用属于该页面上的(1),这是一个通用变量初始化器。什么是不明确的是sumup的类型是什么?

而且,将auto可能是同一这里这样做:

using functionType = int (Linked<int>*); 
    functionType sumup = fold <int , IntOps >; 

这可能是不正确的,但我很好奇,如果我的想法是正确的方向。当实例化时,fold <int , IntOps >将返回int并采用Linked<int>*的单个参数,因此我的using声明是说同样的事情?这是using声明一个真正的“类型”,是auto抵达这个using相同的扣除?

+4

非常接近。简单''自动'衰减,所以你得到一个函数指针类型 - 'int(*)(Linked *)' –

+0

既然你有答案,我想说我发现这个代码的问题有问题。有人会很难弄清楚这个“sumup”是什么。 – SergeyA

+0

@SergeyA是真的,事实上,这是一个普遍的弱点,在任何语言中都有隐式类型推理。动态语言会变得更糟。我仍然发现我更喜欢明确的类型声明,除非这是很难知道的情况,最好留给编译器。 – johnbakers

回答

1

虽然每个函数都有一个类型,但不能有该类型的表达式,也不能有变量。因此int foo(float)的类型为int(float),但您不能拥有该类型的变量。

可以有表情和类型指针功能,所以​​的变量。例如,&foo就是这样一个指向函数的指针。

这两种类型显然是密切相关的。实际上,转换是隐含的:int (*pFoo)(float) = foo;会自动进行转换。

你在这里做的几乎是一样的:int (*sumup)(Linked<int>*) = fold <int , IntOps >;。您看到auto使定义更具可读性。

+0

你绝对可以有函数类型的表达式。 –

+0

@ T.C .:举例? _function调用表达式_没有函数类型。 – MSalters

+0

'int foo(float);',id-表达式'foo'是函数类型'int(float)'的左值。 –

1

auto按照与template argument deduction相同的规则工作。也就是说,当不合格时,它会以价值取胜。既然你在这里返回一个函数引用,它将不得不衰减到一个指针,因为函数没有“值类型”,具有特定的大小和内容。

您还可以使用auto&&进行捕获,这将使sumup的类型为int (&)(Linked<int>*),即对函数的引用。