Another interesting feature of c++11 is the variadic templates. Basically these allow you to add infinite, heterogeneous parameters to your functions. However their syntax seems to force you to define them recursively. As a result they seem to be usable in 2 main ways.
- Map: Apply an repeated operation over the entire list of objects
- Reduce(or fold): Take in the list of objects and compound them into something
How very Hadoop. This apparent limited usability makes them a prime candidate for reduction in a forwarding function. Something that simply recurses the list of parameters and forwards them through a normaliser into a Lambda or directly into a templated function that can handle the specific Type. Here is the Normalize and Lambda approach.
#include <iostream>
#include <sstream>
#include <functional>
template <typename R, typename I>
R normalise(I i)
{
try
{
R item;
std::stringstream s;
s << i;
s >> item;
return item;
}
catch(...)
{}
return R();
}
template <typename R, typename I>
R reduce(std::function<R (const R&, const R&)> action, I i)
{
return normalise<R>(i);
}
template <typename R, typename I, typename... II>
R reduce(std::function<R (const R&, const R&)> action, I i, II... ii)
{
return action(normalise<R>(i), reduce<R>(action, ii...));
}
template <typename R, typename I>
R map(std::function<void (const R&)> action, I i)
{
action(normalise<R>(i));
}
template <typename R, typename I, typename... II>
void map(std::function<void (const R&)> action, I i, II... ii)
{
action(normalise<R>(i));
map<R>(action, ii...);
}
int main()
{
std::function<int (const int&, const int&)> max
= [](const int& a, const int& b)->int { return a>b ? a : b; };
std::function<float (const float&, const float&)> min
= [](const float& a, const float& b)->float { return a<b ? a : b; };
std::function<float (const float&, const float&)> sum
= [](const float& a, const float& b)->float { return a+b; };
std::cout << "Max:" << reduce(max, "452", 3.422, 32, 0x000000ff, "543.485") << "\n";
std::cout << "Min:" << reduce(min, "452", 3.422, 32, 0x000000ff, "543.485") << "\n";
std::cout << "Sum:" << reduce(sum, "452", 3.422, 32, 0x000000ff, "543.485") << "\n";
float res = 0;
std::function<void (const float&)> accum
= [&res](const float& a) { res += a; };
map(accum, "452", 3.422, 32, 0x000000ff, "543.485");
std::cout << "\n" << "Accum:" << res << "\n";
std::stringstream ss;
std::function<void (const float&)> stream = [&ss](const float& a) { ss << a << ","; };
map(stream, "452", 3.422, 32, 0x000000ff, "543.485");
std::cout << ss.str() << "\n";
}
No comments:
Post a Comment