+inline ex ex::subs(const exmap & m, unsigned options) const
+{
+ return bp->subs(m, options);
+}
+
+inline ex subs(const ex & thisex, const exmap & m, unsigned options = 0)
+{ return thisex.subs(m, options); }
+
+inline ex subs(const ex & thisex, const lst & ls, const lst & lr, unsigned options = 0)
+{ return thisex.subs(ls, lr, options); }
+
+inline ex subs(const ex & thisex, const ex & e, unsigned options = 0)
+{ return thisex.subs(e, options); }
+
+
+/* Convert function pointer to function object suitable for map(). */
+class pointer_to_map_function : public map_function {
+protected:
+ ex (*ptr)(const ex &);
+public:
+ explicit pointer_to_map_function(ex x(const ex &)) : ptr(x) {}
+ ex operator()(const ex & e) override { return ptr(e); }
+};
+
+template<class T1>
+class pointer_to_map_function_1arg : public map_function {
+protected:
+ ex (*ptr)(const ex &, T1);
+ T1 arg1;
+public:
+ explicit pointer_to_map_function_1arg(ex x(const ex &, T1), T1 a1) : ptr(x), arg1(a1) {}
+ ex operator()(const ex & e) override { return ptr(e, arg1); }
+};
+
+template<class T1, class T2>
+class pointer_to_map_function_2args : public map_function {
+protected:
+ ex (*ptr)(const ex &, T1, T2);
+ T1 arg1;
+ T2 arg2;
+public:
+ explicit pointer_to_map_function_2args(ex x(const ex &, T1, T2), T1 a1, T2 a2) : ptr(x), arg1(a1), arg2(a2) {}
+ ex operator()(const ex & e) override { return ptr(e, arg1, arg2); }
+};
+
+template<class T1, class T2, class T3>
+class pointer_to_map_function_3args : public map_function {
+protected:
+ ex (*ptr)(const ex &, T1, T2, T3);
+ T1 arg1;
+ T2 arg2;
+ T3 arg3;
+public:
+ explicit pointer_to_map_function_3args(ex x(const ex &, T1, T2, T3), T1 a1, T2 a2, T3 a3) : ptr(x), arg1(a1), arg2(a2), arg3(a3) {}
+ ex operator()(const ex & e) override { return ptr(e, arg1, arg2, arg3); }
+};
+
+template<class C>
+class pointer_to_member_to_map_function : public map_function {
+protected:
+ ex (C::*ptr)(const ex &);
+ C &c;
+public:
+ explicit pointer_to_member_to_map_function(ex (C::*member)(const ex &), C &obj) : ptr(member), c(obj) {}
+ ex operator()(const ex & e) override { return (c.*ptr)(e); }
+};
+
+template<class C, class T1>
+class pointer_to_member_to_map_function_1arg : public map_function {
+protected:
+ ex (C::*ptr)(const ex &, T1);
+ C &c;
+ T1 arg1;
+public:
+ explicit pointer_to_member_to_map_function_1arg(ex (C::*member)(const ex &, T1), C &obj, T1 a1) : ptr(member), c(obj), arg1(a1) {}
+ ex operator()(const ex & e) override { return (c.*ptr)(e, arg1); }
+};
+
+template<class C, class T1, class T2>
+class pointer_to_member_to_map_function_2args : public map_function {
+protected:
+ ex (C::*ptr)(const ex &, T1, T2);
+ C &c;
+ T1 arg1;
+ T2 arg2;
+public:
+ explicit pointer_to_member_to_map_function_2args(ex (C::*member)(const ex&, T1, T2), C &obj, T1 a1, T2 a2) : ptr(member), c(obj), arg1(a1), arg2(a2) {}
+ ex operator()(const ex & e) override { return (c.*ptr)(e, arg1, arg2); }
+};
+
+template<class C, class T1, class T2, class T3>
+class pointer_to_member_to_map_function_3args : public map_function {
+protected:
+ ex (C::*ptr)(const ex &, T1, T2, T3);
+ C &c;
+ T1 arg1;
+ T2 arg2;
+ T3 arg3;
+public:
+ explicit pointer_to_member_to_map_function_3args(ex (C::*member)(const ex &, T1, T2, T3), C &obj, T1 a1, T2 a2, T3 a3) : ptr(member), c(obj), arg1(a1), arg2(a2), arg3(a3) {}
+ ex operator()(const ex & e) override { return (c.*ptr)(e, arg1, arg2, arg3); }
+};
+
+inline ex ex::map(ex f(const ex &)) const
+{
+ pointer_to_map_function fcn(f);
+ return bp->map(fcn);
+}
+
+// convenience type checker template functions
+
+/** Check if ex is a handle to a T, including base classes. */
+template <class T>
+inline bool is_a(const ex &obj)
+{
+ return is_a<T>(*obj.bp);
+}
+
+/** Check if ex is a handle to a T, not including base classes. */
+template <class T>
+inline bool is_exactly_a(const ex &obj)
+{
+ return is_exactly_a<T>(*obj.bp);
+}
+
+/** Return a reference to the basic-derived class T object embedded in an
+ * expression. This is fast but unsafe: the result is undefined if the
+ * expression does not contain a T object at its top level. Hence, you
+ * should generally check the type of e first. Also, you shouldn't cache
+ * the returned reference because GiNaC's garbage collector may destroy
+ * the referenced object any time it's used in another expression.
+ *
+ * @param e expression
+ * @return reference to object of class T
+ * @see is_exactly_a<class T>() */
+template <class T>
+inline const T &ex_to(const ex &e)
+{
+ GINAC_ASSERT(is_a<T>(e));
+ return static_cast<const T &>(*e.bp);
+}
+