& lt; just for fun & gt;
#include <stdarg.h>
#include <string>
#include <vector>
#include <iostream>
#define N 6 // test argument count
void foo(int n, ...);
int main(int, char*[])
{
std::vector strings;
std::wstring s(L"a");
int i(0);
// create unique strings...
for (; i != N; ++i)
{
strings.push_back(s);
++s.front();
}
int n_stack_strings(N*sizeof(std::wstring)), // space needed for strings
n_stack(sizeof(int)+n_stack_strings); // overall stack space...needed for cleanup
__asm sub esp, n_stack_strings ; reserve stack space
std::wstring* p_stack(0);
__asm mov p_stack, esp ; get stack pointer
std::wstring* p(p_stack);
std::vector<std::wstring>::iterator string(strings.begin());
// copy to stack
for (; string != strings.end(); ++string, ++p)
new (p) std::wstring(*string);
__asm push N ; argument count...arguments right to left (__cdecl)
__asm call foo
// cleanup
for (p = p_stack; p != p_stack+N; ++p)
p->~basic_string();
__asm add esp, n_stack ; caller has to cleanup the stack (__cdecl)
return 0;
}
void foo(int n, ...)
{
int i(0);
va_list marker;
va_start(marker, n);
for (; i != n; ++i)
std::wcout << va_arg(marker, std::wstring) << std::endl;
va_end(marker);
}
& lt; / just for fun & gt;
Чтобы понять результат foldTree f g tree
, вы можете использовать эту технику:
tree
, используя конструкторы, например, в вашем примере мы имеем (Node (Node (Leaf 1) (Leaf 2)) (Leaf 4))
. Leaf
на f
и Node
на g
. Для предыдущего примера мы получаем (g (g (f 1) (f 2)) (f 4))
. f
и g
для вычисления результата последнего выражения. Для примера, мы получаем ((+) ((+) ((*2) 1) ((*2) 2)) ((*2) 4))
, который является ((+) ((+) (1*2) (2*2)) (4*2))
, который является ((1*2) + (2*2)) + (4*2)
, который является (2+4)+8 = 14
. Обратите внимание, как мы заменяем Leaf
унарный конструктор на f
, унарную функцию, и Node
, двоичный конструктор с g
, двоичную функцию. Таким образом, у нас всегда есть правильное количество аргументов для наших функций. В общем, типы будут соответствовать просто отлично.