
template <
typename RtnType,
typename ParType1,
typename ParType2,
typename ParType3
> 
RtnType StatRegistry3 <RtnType, ParType1, ParType2, ParType3>::Perform (ParType1 p1, ParType2 p2, ParType3 p3) {
    typename std::vector <ExecFunc> :: iterator i;
    RtnType ret;

    if (!reg) return 0;    

    for (i = reg->begin(); i != reg->end(); i++) {
		if (*i) {
		    ret = (***i) (p1, p2, p3);
			if (ret) return ret;
		}
    }
    return 0;
}

template <
typename RtnType,
typename ParType1,
typename ParType2,
typename ParType3
> 
RtnType StatRegistry3 <RtnType, ParType1, ParType2, ParType3>::Perform (int i, ParType1 p1, ParType2 p2, ParType3 p3) {

    if (!reg) return 0;    
    if (i > reg->size()) return 0;	// should be an exception, rather
    if (! (*reg)[i]) return 0;		// ditto
    return (*(*reg)[i]) (p1, p2, p3);
}

template <
typename RtnType,
typename ParType1,
typename ParType2,
typename ParType3
> 
int  StatRegistry3 <RtnType, ParType1, ParType2, ParType3>::Enlist (ExecFunc e) {
    if (!reg) reg = new std::vector <ExecFunc>;
    reg->push_back (e);
    return 0;
}

template <
typename RtnType,
typename ParType1,
typename ParType2,
typename ParType3
> 
int  StatRegistry3 <RtnType, ParType1, ParType2, ParType3>::Enlist (ExecFunc e, int i) {
    if (!reg) reg = new std::vector <ExecFunc>;
    if (i>=reg->size()) reg->resize (i+1);
    (*reg)[i] = e;
    return 0;
}

//====================================================================================
template <
typename RtnType,
typename ParType1,
typename ParType2
> 
RtnType StatRegistry2 <RtnType, ParType1, ParType2>::Perform (ParType1 p1, ParType2 p2) {
    typename std::vector <ExecFunc> :: iterator i;
    RtnType ret;

    if (!reg) return 0;    

    for (i = reg->begin(); i != reg->end(); i++) {
	if (*i) {
	    ret = (***i) (p1, p2);
	    if (ret) return ret;
	}
    }
    return 0;
}

template <
typename RtnType,
typename ParType1,
typename ParType2
> 
RtnType StatRegistry2 <RtnType, ParType1, ParType2>::Perform (int i, ParType1 p1, ParType2 p2) {
    if (!reg) return 0;    
    if (i > reg->size()) return 0;	// should be an exception, rather
    if (! (*reg)[i]) return 0;		// ditto
    return (*(*reg)[i]) (p1, p2);
}

template <
typename RtnType,
typename ParType1,
typename ParType2
> 
int  StatRegistry2 <RtnType, ParType1, ParType2>::Enlist (ExecFunc e) {
    if (!reg) reg = new std::vector <ExecFunc>;
    reg->push_back (e);
    return 0;
}

template <
typename RtnType,
typename ParType1,
typename ParType2
> 
int  StatRegistry2 <RtnType, ParType1, ParType2>::Enlist (ExecFunc e, int i) {
    if (!reg) reg = new std::vector <ExecFunc>;
    if (i>=reg->size()) reg->resize (i+1);
    (*reg)[i] = e;
    return 0;
}

// ================================================================================
template <
typename RtnType,
typename ParType1
> 
RtnType StatRegistry1 <RtnType, ParType1>::Perform (ParType1 p1) {
    typename std::vector <ExecFunc> :: iterator i;
    RtnType ret;

    if (!reg) return 0;    

    for (i = reg->begin(); i != reg->end(); i++) {
	if (*i) {
	    ret = (***i) (p1);
	    if (ret) return ret;
	}
    }
    return 0;
}

template <
typename RtnType,
typename ParType1
> 
RtnType StatRegistry1 <RtnType, ParType1>::Perform (int i, ParType1 p1) {
    if (!reg) return 0;    
    if (i > reg->size()) return 0;	// should be an exception, rather
    if (! (*reg)[i]) return 0;		// ditto
    return (*(*reg)[i]) (p1);
}

template <
typename RtnType,
typename ParType1
> 
int  StatRegistry1 <RtnType, ParType1>::Enlist (ExecFunc e) {
    if (!reg) reg = new std::vector <ExecFunc>;
    reg->push_back (e);
    return 0;
}

template <
typename RtnType,
typename ParType1
> 
int  StatRegistry1 <RtnType, ParType1>::Enlist (ExecFunc e, int i) {
    if (!reg) reg = new std::vector <ExecFunc>;
    if (i>=reg->size()) reg->resize (i+1);
    (*reg)[i] = e;
    return 0;
}
// ================================================================================
template <
class Functor
>
int StatFtorRegistry<Functor> :: Enlist (Functor* f) {
    if (!reg) reg = new std::vector <Functor*>;
    reg->push_back (f);
    return 0;

}
// -------------------------------------------------------------------------------
template <
class Functor
>
int StatFtorRegistry<Functor> :: Enlist (Functor* f, int i) {
    if (!reg) reg = new std::vector <Functor*>;
    if (i>=reg->size()) reg->resize (i+1);
    (*reg)[i] = f;
    return 0;

}
// -------------------------------------------------------------------------------
template <
class Functor
>
template <
typename RtnType, 
typename ParType1, 
RtnType (Functor:: *Member)(ParType1)
> 
RtnType StatFtorRegistry<Functor> :: Perform (ParType1 p1) {
    typename std::vector <Functor*> :: iterator i;
    RtnType ret;

    if (!reg) return 0;    

    for (i = reg->begin(); i != reg->end(); i++) {
	if (*i) {
	    ret = ((*i) ->* Member) (p1);
	    if (ret) return ret;
	}
    }
    return 0;
}
// -------------------------------------------------------------------------------
template <
class Functor
>
template <
typename RtnType, 
typename ParType1, 
typename ParType2, 
RtnType (Functor:: *Member)(ParType1, ParType2)		//xkubalik
> 
RtnType StatFtorRegistry<Functor> :: Perform (ParType1 p1, ParType2 p2) {
    typename std::vector <Functor*> :: iterator i;
    RtnType ret;

    if (!reg) return 0;    

    for (i = reg->begin(); i != reg->end(); i++) {
	if (*i) {
	    ret = ((*i) ->* Member) (p1,p2);
	    if (ret) return ret;
	}
    }
    return 0;
}
// -------------------------------------------------------------------------------
template <
class Functor
>
template <
typename RtnType, 
typename ParType1, 
typename ParType2, 
typename ParType3, 
RtnType (Functor:: *Member)(ParType1, ParType2, ParType3)
> 
RtnType StatFtorRegistry<Functor> :: Perform (ParType1 p1, ParType2 p2, ParType3 p3) {
    typename std::vector <Functor*> :: iterator i;
    RtnType ret;

    if (!reg) return 0;    

    for (i = reg->begin(); i != reg->end(); i++) {
	if (*i) {
	    ret = ((*i) ->* Member) (p1, p2, p3);
	    if (ret) return ret;
	}
    }
    return 0;
}
// -------------------------------------------------------------------------------
template <
class Functor
>
template <
typename RtnType, 
typename ParType1, 
typename ParType2, 
typename ParType3, 
typename ParType4, 
RtnType (Functor:: *Member)(ParType1, ParType2, ParType3, ParType4)
> 
RtnType StatFtorRegistry<Functor> :: Perform (ParType1 p1, ParType2 p2, ParType3 p3, ParType4 p4) {
    typename std::vector <Functor*> :: iterator i;
    RtnType ret;

    if (!reg) return 0;    

    for (i = reg->begin(); i != reg->end(); i++) {
	if (*i) {
	    ret = ((*i) ->* Member) (p1, p2, p3, p4);
	    if (ret) return ret;
	}
    }
    return 0;
}
// ================================================================================
template <
class Functor
>
int FtorRegistry<Functor> :: Enlist (Functor* f) {
    reg.push_back (f);
    return 0;

}
// -------------------------------------------------------------------------------
template <
class Functor
>
int FtorRegistry<Functor> :: Enlist (Functor* f, int i) {
    if (i>=reg->size()) reg->resize (i+1);
    (*reg)[i] = f;
    return 0;
}
// -------------------------------------------------------------------------------
template <
class Functor
>
template <
typename RtnType, 
typename ParType1, 
RtnType (Functor:: *Member)(ParType1)
> 
RtnType FtorRegistry<Functor> :: Perform (ParType1 p1) {
    typename std::vector <Functor*> :: iterator i;
    RtnType ret;

    for (i = reg.begin(); i != reg.end(); i++) {
	if (*i) {
	    ret = ((*i) ->* Member) (p1);
	    if (ret) return ret;
	}
    }
    return 0;
}
// -------------------------------------------------------------------------------
template <
class Functor
>
template <
typename RtnType, 
typename ParType1, 
typename ParType2, 
RtnType (Functor:: *Member)(ParType1, ParType2)
> 
RtnType FtorRegistry<Functor> :: Perform (ParType1 p1, ParType2 p2) {
    typename std::vector <Functor*> :: iterator i;
    RtnType ret;

    for (i = reg.begin(); i != reg.end(); i++) {
	if (*i) {
	    ret = ((*i) ->* Member) (p1, p2);
	    if (ret) return ret;
	}
    }
    return 0;
}
// -------------------------------------------------------------------------------
template <
class Functor
>
template <
typename RtnType, 
typename ParType1, 
typename ParType2, 
typename ParType3, 
RtnType (Functor:: *Member)(ParType1, ParType2, ParType3)
> 
RtnType FtorRegistry<Functor> :: Perform (ParType1 p1, ParType2 p2, ParType3 p3) {
    typename std::vector <Functor*> :: iterator i;
    RtnType ret;

    for (i = reg.begin(); i != reg.end(); i++) {
	if (*i) {
	    ret = ((*i) ->* Member) (p1, p2, p3);
	    if (ret) return ret;
	}
    }
    return 0;
}

// -------------------------------------------------------------------------------
template <
class Functor
>
template <
typename RtnType, 
typename ParType1, 
typename ParType2, 
typename ParType3, 
typename ParType4, 
RtnType (Functor:: *Member)(ParType1, ParType2, ParType3, ParType4)
> 
RtnType FtorRegistry<Functor> :: Perform (ParType1 p1, ParType2 p2, ParType3 p3, ParType4 p4) {
    typename std::vector <Functor*> :: iterator i;
    RtnType ret;

    for (i = reg.begin(); i != reg.end(); i++) {
	if (*i) {
	    ret = ((*i) ->* Member) (p1, p2, p3, p4);
	    if (ret) return ret;
	}
    }
    return 0;
}
// ================================================================================
template <
typename RtnType,
typename ParType1,
typename ParType2
> 
template <
typename ActualType1, 
typename ActualType2,
RtnType (*callback) (ActualType1, ActualType2)
>
int StatDoubleReg <RtnType, ParType1, ParType2> :: Enlist (void) {

    struct Local {
	static RtnType Trampoline (ParType1 p1, ParType2 p2) {
	    return (*callback) (dynamic_cast <ActualType1> (p1), dynamic_cast <ActualType2> (p2)); 
	}
    };

    if (!reg) reg = new MapType;

    reg->insert (std::pair <KeyType, ExecFunc> ( KeyType (& typeid (ActualType1), & typeid (ActualType2)), &Local::Trampoline ));
#ifdef dbg
    std::cerr << "enlist:  id " 
	<< hex 
	<< & typeid (ActualType1) << " " 
	<< & typeid (ActualType2) << " "
	<< typeid (ActualType1).name() << " " 
	<< typeid (ActualType2).name() << "\n"; 
#endif
    return 0;
}

template <
typename RtnType,
typename ParType1,
typename ParType2
> 
RtnType StatDoubleReg <RtnType, ParType1, ParType2> :: Perform (ParType1 p1, ParType2 p2) {
    if (!reg) return 0;
    typename MapType::iterator loc = reg->find (KeyType (& typeid (p1), & typeid (p2)));
    if (loc == reg->end()) { 
#ifdef dbg
	std::cerr << "not found: id " << hex 
	    << & typeid (p1) << " " 
	    << & typeid (p2) << " "
	    << typeid (p1).name() << " "
	    << typeid (p2).name() << "\n"; 
#endif
	return 0; 
    }
    return (*(loc->second)) (p1, p2);
}
