:
namespace detail {
struct const_tag;
struct nonconst_tag;
template<typename U, typename>
struct delay_lookup;
template<typename U>
struct delay_lookup<U, nonconst_tag>
{
typedef typename U::template get_impl<
typename U::derived_type>::type impl_type;
impl_type* u;
delay_lookup(impl_type* u):u(u) { }
impl_type* operator->() { return u; }
};
template<typename U>
struct delay_lookup<U, const_tag> {
typedef typename U::template get_impl<
typename U::derived_type>::type const impl_type;
impl_type* u;
delay_lookup(impl_type* u):u(u) { }
impl_type* operator->() { return u; }
};
}
template<typename T>
struct pre_call {
private:
friend class detail::delay_lookup<pre_call, detail::const_tag>;
friend class detail::delay_lookup<pre_call, detail::nonconst_tag>;
typedef T derived_type;
template<typename U> struct get_impl {
typedef typename U::impl type;
};
protected:
typedef boost::function<void(T const&)> fun_type;
fun_type pre;
template<typename Fun>
pre_call(Fun pre):pre(pre) { }
public:
detail::delay_lookup<pre_call, detail::nonconst_tag> operator->() {
pre(*get_derived());
return detail::delay_lookup<pre_call,
detail::nonconst_tag>(&get_derived()->d);
}
detail::delay_lookup<pre_call, detail::const_tag> operator->() const {
pre(*get_derived());
return detail::delay_lookup<pre_call,
detail::const_tag>(&get_derived()->d);
}
private:
T * get_derived() {
return static_cast<T *>(this);
}
T const* get_derived() const {
return static_cast<T const*>(this);
}
};
:
struct foo : pre_call<foo> {
private:
struct impl {
void some() const {
std::cout << "some!" << std::endl;
}
void stuff() {
std::cout << "stuff!" << std::endl;
}
};
void pre() const {
std::cout << "pre!" << std::endl;
}
friend struct pre_call<foo>;
impl d;
public:
foo():pre_call<foo>(&foo::pre) { }
};
int main() {
foo f;
f->some();
f->stuff();
}
, post. . . , - " ". operator- > - pre,
: , .