C ++ 0x Template Function Object Output

I am a Scala / Java programmer who wants to introduce themselves again in C ++ and learn some interesting functions in C ++ 0x. I wanted to start by developing my own library with small functional libraries based on Scala collections so that I could get a clear idea of ​​the templates. The problem I am facing is that the compiler cannot output type information for the template objects of the function.

FC ++ seems to have resolved this with Signature. They seem really like a name like result_type, and I thought I was getting it using the new function syntax. Can anyone suggest a way to do such things in C ++ 0x, if possible, or at least explain how FC ++ was able to do this? Here is a snippet of code that I played with

#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.
}
+5
source share
3 answers

You can also make a template. operator()

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

Then you can go through Print(). For passing arguments like in ArrayBuffer<decltype(fn(T()))>, I recommend using declval, so you can also work with constructiveT

ArrayBuffer<decltype(fn(declval<T>()))>
+5
source

, ++. .
++ .

, ++.

  • -. algrithm , .
    ArrayBuffer::foreach == std::for_each
    ArrayBuffer::map == std::transform
  • , . ++, Java # . /, . . , ( - ).

++. , # . , #. Java , -, .

struct Print
{
   template<typename T>
   void operator()( const T& t )
   { std::cout << t << std::endl; }
};

struct Squared
{
   template<typename T>
   T operator()( const T& t )
   { return t*t; }
};

int main()
{
   std::vector<int> vi;
   std::foreach( vi.begin(), vi.end(), Print());
   std::foreach( vi.begin(), vi.end(), [](int i){ std::cout<<i<<std::endl; } );

   std::vector<int> vi_squared;

   std::transform( vi.begin(), vi.end(), std::back_inserter(vi_squared), Squared() );
   // or
   vi_squared.resize( vi.size() );
   std::transform( vi.begin(), vi.end(), vi_squared.begin(), Squared() );
}
+1

, int?

, int.
.

iterable.foreach(Print<float>());

, , -. , ?

- . , . . , , .

0
source

All Articles