Commits

Volker Braun committed af5e2c9

framework for explicit template instantiation

  • Participants
  • Parent commits b7fe62b

Comments (0)

Files changed (5)

File ginac/Makefile.am

   operators.cpp power.cpp registrar.cpp relational.cpp remember.cpp \
   pseries.cpp print.cpp symbol.cpp symmetry.cpp tensor.cpp \
   utils.cpp wildcard.cpp \
-  remember.h tostring.h utils.h compiler.h order.cpp
+  remember.h tostring.h utils.h compiler.h order.cpp templates.cpp
 
 #The -no-undefined breaks Pynac on OS X 10.4.  See #9135
 if CYGWIN
   exprseq.h fail.h fderivative.h flags.h function.h hash_map.h idx.h indexed.h \
   inifcns.h integral.h lst.h matrix.h mul.h ncmul.h normal.h numeric.h operators.h \
   power.h print.h pseries.h ptr.h registrar.h relational.h structure.h \
-  symbol.h symmetry.h tensor.h version.h wildcard.h order.h
+  symbol.h symmetry.h tensor.h version.h wildcard.h order.h \
+  templates.h extern_templates.h
 EXTRA_DIST = version.h.in

File ginac/container.h

 
 	// non-virtual functions in this class
 private:
-	void sort_(std::random_access_iterator_tag)
+	void sort_()
 	{
 		std::sort(this->seq.begin(), this->seq.end(), ex_is_less());
 	}
 
-	void sort_(std::input_iterator_tag)
-	{
-		this->seq.sort(ex_is_less());
-	}
-
 	void unique_()
 	{
 		typename STLT::iterator p = std::unique(this->seq.begin(), this->seq.end(), ex_is_equal());
 	return *this;
 }
 
+/** Specialization of container::prepend() for std::vector. */
+template<> inline container<std::vector> & container<std::vector>::prepend(const ex & b)
+{
+	ensure_if_modifiable();
+	this->seq.insert(this->seq.begin(), b);
+	return *this;
+}
+
 /** Add element at back. */
 template <template <class T, class = std::allocator<T> > class C>
 container<C> & container<C>::append(const ex & b)
 	return *this;
 }
 
+/** Specialization of container::remove_first() for std::vector. */
+template<> inline container<std::vector> & container<std::vector>::remove_first()
+{
+	ensure_if_modifiable();
+	this->seq.erase(this->seq.begin());
+	return *this;
+}
+
 /** Remove last element. */
 template <template <class T, class = std::allocator<T> > class C>
 container<C> & container<C>::remove_last()
 container<C> & container<C>::sort()
 {
 	ensure_if_modifiable();
-	sort_(typename std::iterator_traits<typename STLT::iterator>::iterator_category());
+	sort_();
 	return *this;
 }
 
+/** Specialization of container::sort_() for std::list. */
+template<> inline void container<std::list>::sort_()
+{
+	this->seq.sort(ex_is_less());
+}
+
 /** Specialization of container::unique_() for std::list. */
 template<> inline void container<std::list>::unique_()
 {

File ginac/extern_templates.h

+/** @file extern_templates.h
+ *
+ *  Include this header to declare GiNaC templates external. If
+ *  nothing else, this saves time and space when compiling the
+ *  application that uses libpynac. 
+ * 
+ *  Note that you cannot use pynac with templates that were
+ *  instantiated outside of pynac since RTTI does not work across DSO
+ *  boundaries. See templates.cpp for more details.
+ *
+ *  You should always include this header in your application after
+ *  including <pynac/ginac.h>.
+ * 
+ *  */
+
+#ifndef PYNAC_EXTERN_TEMPLATES__H
+#define PYNAC_EXTERN_TEMPLATES__H
+
+#ifndef __GINAC_H__
+#error You must #include <pynac/ginac.h> first!
+#endif
+
+#define TEMPLATE(cls) extern template cls
+#include "templates.h"
+#undef TEMPLATE
+
+#endif

File ginac/templates.cpp

+/** @file templates.cpp
+ *
+ *  This source file explicitly instantiates templates. This is
+ *  important since RTTI does not work (reliably) across DSO
+ *  boundaries. If libpynac does not contain a template instantiation
+ *  but the application using libpynac does, then you will get
+ *  mysterious std::bad_cast errors when you pass these instantiations
+ *  into pynac. See http://trac.sagemath.org/ticket/14780
+ * 
+ *  */
+
+#ifndef PYNAC_TEMPLATES__H
+#define PYNAC_TEMPLATES__H
+
+#include "ginac.h"
+
+#define TEMPLATE(cls) template cls
+#include "templates.h"
+#undef TEMPLATE
+
+#endif
+

File ginac/templates.h

+/** @file templates.h
+ *
+ *  This file lists important c++ templates to use pynac. Depending on
+ *  the definition of the TEMPLATE macro, this can be used to
+ *  explicitly instantiate these templates (see templates.cpp) or
+ *  declare the templates as external (see extern_templates.h)
+ *  
+ *  Note: You cannot use typedefs in external template
+ *        declarations. The usual typedef'ed name in GiNaC is
+ *        indicated in the comments below
+ *
+ *  You should only include this file if you know what you are doing.
+ * 
+ *  */
+
+
+
+TEMPLATE(class std::vector<GiNaC::ex>);            // GiNaC::exvector;
+TEMPLATE(class GiNaC::container<std::vector>);     // GiNaC::exprseq;