C++ 0x模板函数对象推断

Jos*_*man 5 c++ templates functional-programming function-pointers c++11

我是一名Scala/Java程序员,希望将自己重新引入C++并学习C++ 0x中的一些令人兴奋的功能.我想从设计我自己的稍微功能的集合库开始,基于Scala的集合,这样我就可以深入理解模板.我遇到的问题是编译器似乎无法推断模板化函数对象的任何类型信息.

FC++似乎已经使用"签名"解决了这个问题.这些看起来与result_type typename非常相似,我想我会使用新的函数语法来实现它.任何人都可以提出一种在C++ 0x中做这种事情的方法,如果可能的话,或者至少解释一下FC++是如何实现这一目标的?这是我正在玩的代码片段

#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

template<class T>
class ArrayBuffer {
private:
    vector<T> array;
public:
    ArrayBuffer();
    ArrayBuffer(vector<T> a) : array(a) {}

    template<typename Fn>
    void foreach(Fn fn) {
        for(unsigned int i = 0; i < array.size(); i++) fn(array[i]);
    }

    template<typename Fn>
    auto map(Fn fn) -> ArrayBuffer<decltype(fn(T()))> {
        vector<decltype(fn(T()))> result(array.size());
        for(int unsigned i = 0; i < array.size(); i++) result[i] = fn(array[i]);
        return result;
    }
};

template<typename T>
class Print {
    public:
    void operator()(T elem) { cout<<elem<<endl; }
};

template<typename T>
class Square{
public:
    auto operator()(T elem) -> T {
        return elem * elem;
    }
};

int main() {
    vector<int> some_list = {5, 3, 1, 2, 4};
    ArrayBuffer<int> iterable(some_list);
    ArrayBuffer<int> squared = iterable.map(Square<int>()); // works as expected
    iterable.foreach(Print<int>()); // Prints 25 9 1 4 16 as expected
    iterable.foreach(Print()); // Is there a way or syntax for the compiler to infer that the template must be an int?
    ArrayBuffer<int> squared2 = iterable.map(Square()); // Same as above - compiler should be able to infer the template.
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*itb 5

你也可以制作operator()一个模板

class Print {
    public:
    template<typename T>
    void operator()(T elem) { cout<<elem<<endl; }
};
Run Code Online (Sandbox Code Playgroud)

然后你可以通过Print().对于像ArrayBuffer<decltype(fn(T()))>我建议使用的那样传递参数declval,所以你也可以使用非默认的可构造的T

ArrayBuffer<decltype(fn(declval<T>()))>
Run Code Online (Sandbox Code Playgroud)