Dobrý deň včera som narazil na jeden problém s funkcionálnymi typmi v C++. Išlo tam o jednu špecifickú higher-order funkciu (tú sem ťahať nebudem), ale skúsim to vysvetliť na príklade - bežnej higher-order funkcii map, ktorú asi pozná každý programátor.
dajme tomu že máme "modul" Vector a v ňom funkciu Vector::map ktorá má dva parametre:
1. mapper: Mapper<T1, T2>
2. list: vector<T>
Typ Mapper je funnckionálny typ:
template<typename T1, typename T2> using Mapper = T2(__stdcall*)(T1 item);
Funkcia Vector::map vyzerá nejako takto:
static struct Vector
{
template<typename T1, typename T2>
static std::vector<T2> map(const Mapper<T1, T2> mapper, const std::vector<T1> list)
{
...implementácia
}
}
Dajme tomu že chcem druhú mocninu položiek vektora:
const auto numbers = std::vector<int>{ 1, 2, 3 };
const auto squares = Vector::map(
(Mapper<int, int>)[](int a) -> int { return a * a; },
numbers
);
Vector::dump(squares);
Zatiaľ je všetko ok, no problém nastane keď chcem do tej lambdy dostať nejaké dáta z vonku. Dajme tomu, že mám číslo a všetky položky vectoru chcem vynásobiť týmto číslom. Ako to číslo dostanem do vnútra funkcie? Ak povolím lambde captures "[=]" alebo "[&]" tak už tá lambda nesedí s typom Mapper a (takú) lambdu v tomto prípade nemôžem použiť:
const auto numbers = std::vector<int>{ 1, 2, 3 };
const auto multiplier = 5; //ako tam dostanem tuto premennu?
const auto squares = Vector::map(
(Mapper<int, int>)[=](int a) -> int { return a * multiplier; }, // pri použití [=] alebo [&] prekladač vyhodí chybu
numbers
);
Vector::dump(squares);
Rovnako nejde do parametra vložiť metódu objektu (dá sa vložiť len statická metóda bez this). Vo funkcionálnych jazykoch by som použil buď currying, lambdu, ale C++ je na toto príliš striktné. Jediné čo ma napadlo je použiť statickú triedu so statickým memberom, lenže to je prasárna (a dosť nebezpečná prasárna). Máte nejaký nápad ako tento problém obísť? Vopred ďakujem.