Re: Access Data Items In Ancestor Stack Frames Safely (Dr.Dobb's article)
One step further - see below. But how to handle the variable function
arguments? Pack and unpack between exec(...) and exec_wrapper(...)?
================================
/*
* StackAccess.h
*
* Created on: May 31, 2013
* Author: frank
*/
#ifndef STACKACCESS_H_
#define STACKACCESS_H_
#include <functional> // std::mem_fn
struct Nop
{
};
template <typename CALLER>
struct Func_Impl
{
typedef CALLER caller_type;
caller_type * caller;
};
template <typename IMPL, typename... ARGS>
struct Func : virtual Func_Impl<typename IMPL::caller_type>
{
typedef typename
decltype(std::mem_fn(&IMPL::exec_impl))::result_type return_type;
virtual return_type exec_wrap(ARGS...) = 0;
virtual ~Func() { }
return_type exec(
typename IMPL::caller_type * caller,
ARGS... args)
{
Func_Impl<typename IMPL::caller_type>::caller = caller;
return exec_wrap(args...);
}
};
#endif /* STACKACCESS_H_ */
================================
/*
* main.cpp
*
* Created on: May 24, 2013
* Author: frank
*/
#include <iostream>
#include "StackAccess.h"
template <typename CALLER>
struct Func3_Impl : virtual Func_Impl<CALLER>
{
typedef Func3_Impl type;
void exec_impl(void)
{
std::cout << "Func3: entered" << std::endl;
std::cout << "caller->x = "
<< this->caller->x << std::endl;
std::cout << "caller->caller->x = "
<< this->caller->caller->x
<< std::endl;
}
};
template <class CALLER>
struct Func3 : public Func3_Impl<CALLER>,
public Func<
Func3_Impl<CALLER> >
{
typedef typename Func<Func3_Impl<CALLER> >::return_type
return_type;
inline return_type exec_wrap(void)
{
return this->exec_impl();
}
};
template <typename CALLER>
struct Func2_Impl : virtual Func_Impl<CALLER>
{
typedef Func2_Impl type;
int x = 2;
int exec_impl (
int p_val)
{
std::cout << "Func2: entered" << std::endl;
std::cout << "p_val = " << p_val << std::endl;
std::cout << "caller->x = " << this->caller->x << std::endl;
this->caller->x = 3;
Func3<type>().exec(this);
return 7;
}
};
template <class CALLER>
struct Func2 : public Func2_Impl<CALLER>,
public Func<
Func2_Impl<CALLER>,
int> // TODO: how to handle variable arguments?
{
typedef typename Func<Func2_Impl<CALLER> >::return_type
return_type;
inline return_type exec_wrap(
int p_val) // TODO: want to be generic here
{
return this->exec_impl(p_val);
}
};
template <typename CALLER>
struct Func1_Impl : virtual Func_Impl<CALLER>
{
typedef Func1_Impl type;
int x = 1;
void exec_impl (void)
{
std::cout << "Func1: entered" << std::endl;
int getVal = Func2<type>().exec(this, 5);
std::cout << "Func2 returns #" << getVal
<< ", x = " << x << std::endl;
}
};
template <class CALLER>
struct Func1 : public Func1_Impl<CALLER>,
public Func<
Func1_Impl<CALLER> >
{
typedef typename Func<Func1_Impl<CALLER> >::return_type
return_type;
inline return_type exec_wrap(void)
{
return this->exec_impl();
}
};
int main(
int argc,
char ** argv)
{
Nop nop;
Func1<Nop>().exec(&nop);
return 0;
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]