/** * \file rmf/macros.h \brief Various general useful macros for IMP. * * Copyright 2007-2011 IMP Inventors. All rights reserved. * */ #ifndef RMF_MACROS_H #define RMF_MACROS_H #ifdef IMP_DOXYGEN #define RMF_REQUIRE_SEMICOLON_CLASS(Name) #define RMF_REQUIRE_SEMICOLON_NAMESPACE #elif defined(SWIG) #define RMF_REQUIRE_SEMICOLON_CLASS(Name) #define RMF_REQUIRE_SEMICOLON_NAMESPACE #elif defined(__clang__) #define RMF_REQUIRE_SEMICOLON_CLASS(Name) #define RMF_REQUIRE_SEMICOLON_NAMESPACE #else #define RMF_REQUIRE_SEMICOLON_CLASS(Name) \ RMF_NO_DOXYGEN(RMF_NO_SWIG(friend void dummy_f_##Name())) #define RMF_REQUIRE_SEMICOLON_NAMESPACE void dummy_f() #endif #ifdef IMP_DOXYGEN //! Hide something from doxygen /** */ #define RMF_NO_DOXYGEN(x) //! Only show something to doxygen /** */ #define RMF_ONLY_DOXYGEN(x) x RMF_REQUIRE_SEMICOLON_CLASS(only_doxy) #define RMF_SWITCH_DOXYGEN(x,y) x #else #define RMF_NO_DOXYGEN(x) x #define RMF_ONLY_DOXYGEN(x) RMF_REQUIRE_SEMICOLON_CLASS(only_doxy) #define RMF_SWITCH_DOXYGEN(x,y) y #endif #if defined(SWIG) #define RMF_NO_SWIG(x) #else //! Hide the line when SWIG is compiled or parses it /** */ #define RMF_NO_SWIG(x) x #endif #if defined(IMP_DOXYGEN) /** \name Comparisons Helper macros for implementing comparisons in terms of either member variables or a member compare function. All of the <,>,== etc are implemented for both C++ and Python. @{ */ //! Implement comparison in a class using a compare function /** The compare function should take a const Name & and return -1, 0, 1 as appropriate. */ #define RMF_COMPARISONS(Name) //! Implement comparison in a class using field as the variable to compare /** \param[in] Name the name of the class \param[in] field the first field to compare on */ #define RMF_COMPARISONS_1(Name, field) //! Implement comparison in a class using field as the variable to compare /** \param[in] Name the name of the class \param[in] f0 the first field to compare on \param[in] f1 the second field to compare on */ #define RMF_COMPARISONS_2(Name, f0, f1) //! Implement comparison in a class using field as the variable to compare /** \param[in] Name the name of the class \param[in] f0 the first field to compare on \param[in] f1 the second field to compare on \param[in] f2 the third field to compare on */ #define RMF_COMPARISONS_3(Name, f0, f1, f2) /** @} */ #elif defined(SWIG) #define RMF_SWIG_COMPARISONS(Name) \ bool __eq__(const Name &o) const; \ bool __ne__(const Name &o) const; \ bool __lt__(const Name &o) const; \ bool __gt__(const Name &o) const; \ bool __ge__(const Name &o) const; \ bool __le__(const Name &o) const #define RMF_COMPARISONS(Name) \ RMF_SWIG_COMPARISONS(Name) #define RMF_COMPARISONS_1(Name, field) \ RMF_SWIG_COMPARISONS(Name) #define RMF_COMPARISONS_2(Name, f0, f1) \ RMF_SWIG_COMPARISONS(Name) #define RMF_COMPARISONS_3(Name f0, f1, f2) \ RMF_SWIG_COMPARISONS(Name) #else // not doxygen #define RMF_SWIG_COMPARISONS(Name) \ bool __eq__(const Name &o) const { \ return operator==(o); \ } \ bool __ne__(const Name &o) const { \ return operator!=(o); \ } \ bool __lt__(const Name &o) const { \ return operator<(o); \ } \ bool __gt__(const Name &o) const { \ return operator>(o); \ } \ bool __ge__(const Name &o) const { \ return operator>=(o); \ } \ bool __le__(const Name &o) const { \ return operator<=(o); \ } \ int __cmp__(const Name &o) const { \ return compare(o); \ } \ RMF_REQUIRE_SEMICOLON_CLASS(comparisons) #define RMF_COMPARISONS(Name) \ RMF_SWIG_COMPARISONS(Name); \ bool operator==(const Name &o) const { \ return (Name::compare(o) == 0); \ } \ bool operator!=(const Name &o) const { \ return (Name::compare(o) != 0); \ } \ bool operator<(const Name &o) const { \ return (Name::compare(o) <0); \ } \ bool operator>(const Name &o) const { \ return (compare(o) > 0); \ } \ bool operator>=(const Name &o) const { \ return !(Name::compare(o) < 0); \ } \ bool operator<=(const Name &o) const { \ return !(Name::compare(o) > 0); \ } \ template friend int compare(const T&a, const T&b) #define RMF_COMPARISONS_1(Name, field) \ bool operator==(const Name &o) const { \ return (field== o.field); \ } \ bool operator!=(const Name &o) const { \ return (field!= o.field); \ } \ bool operator<(const Name &o) const { \ return (field< o.field); \ } \ bool operator>(const Name &o) const { \ return (field> o.field); \ } \ bool operator>=(const Name &o) const { \ return (field>= o.field); \ } \ bool operator<=(const Name &o) const { \ return (field<= o.field); \ } \ int compare(const Name &o) const { \ if (operator<(o)) return -1; \ else if (operator>(o)) return 1; \ else return 0; \ } \ RMF_SWIG_COMPARISONS(Name) #define RMF_COMPARISONS_2(Name, f0, f1) \ bool operator==(const Name &o) const { \ return (f0== o.f0 && f1==o.f1); \ } \ bool operator!=(const Name &o) const { \ return (f0!= o.f0 || f1 != o.f1); \ } \ bool operator<(const Name &o) const { \ if (f0< o.f0) return true; \ else if (f0 > o.f0) return false; \ else return f1 < o.f1; \ } \ bool operator>(const Name &o) const { \ if (f0 > o.f0) return true; \ else if (f0 < o.f0) return false; \ else return f1 > o.f1; \ } \ bool operator>=(const Name &o) const { \ return operator>(o) || operator==(o); \ } \ bool operator<=(const Name &o) const { \ return operator<(o) || operator==(o); \ } \ int compare(const Name &o) const { \ if (operator<(o)) return -1; \ else if (operator>(o)) return 1; \ else return 0; \ } \ RMF_SWIG_COMPARISONS(Name) #define RMF_COMPARISONS_3(Name, f0, f1, f2) \ bool operator==(const Name &o) const { \ return (f0== o.f0 && f1==o.f1 && f2 == o.f2); \ } \ bool operator!=(const Name &o) const { \ return (f0!= o.f0 || f1 != o.f1 || f2 != o.f2); \ } \ bool operator<(const Name &o) const { \ if (f0< o.f0) return true; \ else if (f0 > o.f0) return false; \ if (f1< o.f1) return true; \ else if (f1 > o.f1) return false; \ else return f2 < o.f2; \ } \ bool operator>(const Name &o) const { \ if (f0 > o.f0) return true; \ else if (f0 < o.f0) return false; \ if (f1 > o.f1) return true; \ else if (f1 < o.f1) return false; \ else return f2 > o.f2; \ } \ bool operator>=(const Name &o) const { \ return operator>(o) || operator==(o); \ } \ bool operator<=(const Name &o) const { \ return operator<(o) || operator==(o); \ } \ int compare(const Name &o) const { \ if (operator<(o)) return -1; \ else if (operator>(o)) return 1; \ else return 0; \ } \ RMF_SWIG_COMPARISONS(Name) #endif /** \name Swap helpers Use the swap_with member function to swap two objects. The two objects mustbe of the same type (Name) and define the method \c swap_with(). The number suffix is the number of template arguments, all of which must be of class type. @{ */ #define RMF_SWAP(Name) \ inline void swap(Name &a, Name &b) {a.swap_with(b);} \ RMF_REQUIRE_SEMICOLON_NAMESPACE #define RMF_SWAP_1(Name) \ template \ inline void swap(Name &a, Name &b) {a.swap_with(b);} \ RMF_REQUIRE_SEMICOLON_NAMESPACE #define RMF_SWAP_2(Name) \ template \ inline void swap(Name &a, Name &b) { \ a.swap_with(b); \ } \ RMF_REQUIRE_SEMICOLON_NAMESPACE #define RMF_SWAP_3(Name) \ template \ inline void swap(Name &a, Name &b) { \ a.swap_with(b); \ } \ RMF_REQUIRE_SEMICOLON_NAMESPACE /** @} */ //! Swap two member variables assuming the other object is called o /** Swap the member \c var_name of the two objects (this and o). */ #define RMF_SWAP_MEMBER(var_name) \ std::swap(var_name, o.var_name) //! Use a copy_from method to create a copy constructor and operator= /** This macro is there to aid with classes which require a custom copy constructor. It simply forwards \c operator= and the copy constructor to a method \c copy_from() which should do the copying. You should think very hard before implementing a class which requires a custom copy custructor as it is easy to get wrong and you can easily wrap most resources with RAII objects (\external{en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization, wikipedia entry}). */ #define RMF_COPY_CONSTRUCTOR(Name, Base) Name(const Name &o): Base() \ {copy_from(o);} \ RMF_NO_SWIG(Name& operator=(const Name &o) {copy_from(o); return *this;}) \ RMF_REQUIRE_SEMICOLON_CLASS(copy) #ifdef _MSC_VER // VC doesn't understand friends properly #define RMF_REF_COUNTED_DESTRUCTOR(Name) \ public: \ virtual ~Name(){} \ RMF_REQUIRE_SEMICOLON_CLASS(destructor) #define RMF_REF_COUNTED_INLINE_DESTRUCTOR(Name, dest) \ public: \ virtual ~Name(){dest} \ RMF_REQUIRE_SEMICOLON_CLASS(destructor) #define RMF_REF_COUNTED_NONTRIVIAL_DESTRUCTOR(Name) \ public: \ virtual ~Name() #elif defined(SWIG) // SWIG doesn't do friends right either, but we don't care as much #define RMF_REF_COUNTED_DESTRUCTOR(Name) \ public: \ virtual ~Name(){} \ RMF_REQUIRE_SEMICOLON_CLASS(destructor) #define RMF_REF_COUNTED_INLINE_DESTRUCTOR(Name, dest) \ public: \ virtual ~Name(){dest} \ RMF_REQUIRE_SEMICOLON_CLASS(destructor) #define RMF_REF_COUNTED_NONTRIVIAL_DESTRUCTOR(Name) \ public: \ virtual ~Name() #elif defined(IMP_DOXYGEN) /* The destructor is unprotected for SWIG since if it is protected SWIG does not wrap the Python proxy distruction and so does not dereference the ref counted pointer. SWIG also gets confused on template friends. */ //! Ref counted objects should have private destructors /** This macro defines a private destructor and adds the appropriate friend methods so that the class can be used with ref counting. By defining a private destructor, you make it so that the object cannot be declared on the stack and so must be ref counted. \see RMF_REF_COUNTED_NONTRIVIAL_DESTRUCTOR() \see IMP::RefCounted */ #define RMF_REF_COUNTED_DESTRUCTOR(Name) /** Like RMF_REF_COUNTED_DESTRUCTOR(), but the destructor is only declared, not defined. */ #define RMF_REF_COUNTED_NONTRIVIAL_DESTRUCTOR(Name) /** Like RMF_REF_COUNTED_DESTRUCTOR(), but the destructor is declared inline. */ #define RMF_REF_COUNTED_INLINE_DESTRUCTOR(Name, destructor) #else #define RMF_REF_COUNTED_DESTRUCTOR(Name) \ protected: \ template friend struct IMP::internal::RefStuff; \ virtual ~Name(){} \ public: \ RMF_REQUIRE_SEMICOLON_CLASS(destructor) #define RMF_REF_COUNTED_INLINE_DESTRUCTOR(Name, dest) \ protected: \ template friend struct IMP::internal::RefStuff; \ virtual ~Name(){dest} \ public: \ RMF_REQUIRE_SEMICOLON_CLASS(destructor) #define RMF_REF_COUNTED_NONTRIVIAL_DESTRUCTOR(Name) \ protected: \ template friend struct IMP::internal::RefStuff; \ virtual ~Name(); \ public: \ RMF_REQUIRE_SEMICOLON_CLASS(destructor) #endif #ifdef IMP_DOXYGEN /** Implement operator[] for C++ and python. The index type is Index and the expression that returns the value is expr. If the bounds_check_expr is false, then a UsageException is thrown in C++ or and IndexException if called from python. */ #define RMF_BRACKET(Value, Index, bounds_check_expr, expr) \ const Value operator[](Index) const; \ Value& operator[](Index); /** Implement operator[] for C++ and python. The index type is Index and the expression that returns the value is expr. The value returned is not mutable. If the bounds_check_expr is false, then a UsageException is thrown in C++ or and IndexException if called from python. */ #define RMF_CONST_BRACKET(Value, Index, bounds_check_expr, expr) \ const Value operator[](Index) const; \ Value& operator[](Index); #elif !defined(SWIG) #define RMF_CONST_BRACKET(Value, Index, bounds_check_expr, expr) \ const Value& operator[](Index i) const { \ RMF_USAGE_CHECK((bounds_check_expr), "Index out of range: "<< i); \ expr; \ } \ const Value& __getitem__(Index i) const { \ if (!(bounds_check_expr)) { \ RMF_THROW("Bad index " << i, IndexException); \ } \ expr; \ } \ #define RMF_BRACKET(Value, Index, bounds_check_expr, expr) \ Value& operator[](Index i) { \ RMF_USAGE_CHECK((bounds_check_expr), "Index out of range: "<< i); \ expr; \ } \ void __setitem__(Index i, const Value &v) { \ operator[](i)=v; \ } \ RMF_CONST_BRACKET(Value, Index, bounds_check_expr, expr) #else #define RMF_CONST_BRACKET(Value, Index, bounds_check_expr, expr) \ const Value& __getitem__(Index i) const { \ if (!(bounds_check_expr)) { \ RMF_THROW("Bad index " << i, IndexException); \ } \ expr; \ } #define RMF_BRACKET(Value, Index, bounds_check_expr, expr) \ void __setitem__(Index i, const Value &v) { \ operator[](i)=v; \ } \ RMF_CONST_BRACKET(Value, Index, bounds_check_expr, expr) #endif #ifdef IMP_DOXYGEN //! Define the type for storing sets of values /** The macro defines the type Names. PluralName should be Names unless the English spelling is different. This macro also defines the output operator for the type. See \ref values "Value and Objects" for a description of what it means to be an object vs a value in \imp. */ #define RMF_VALUES(Name, PluralName) #else #define RMF_VALUES(Name, PluralName) \ RMF_OUTPUT_OPERATOR(Name); \ typedef std::vector PluralName #endif #ifdef IMP_DOXYGEN /** \name Showable Declare the methods needed by an object that can be printed, both from C++ and Python. Each value-type class should have an RMF_SHOWABLE() call internal to it and an RMF_OUTPUT_OPERATOR() call external to it. The suffixs are the number of template arguments that the object has (eg _1 means one template argument). _D means one integer template argument. @{ */ /** This macro declares the method - void show(std::ostream &out) const It also makes it so that the object can be printed in Python. The \c ostream and \c sstream headers must be included. See also RMF_SHOWABLE_INLINE(). Do not use with IMP::Object objects as they have their own show mechanism. */ #define RMF_SHOWABLE(Name) //! Declare the methods needed by an object that can be printed /** This macro declares the method - \c void \c show(std::ostream &out) const It also makes it so that the object can be printed in Python. The \c ostream and \c sstream headers must be included. See also RMF_SHOWABLE_INLINE() */ #define RMF_SHOWABLE_INLINE(Name, how_to_show) //! Implement operator<< on class name, assuming it has one template argument /** \copydetails RMF_OUTPUT_OPERATOR */ #define RMF_OUTPUT_OPERATOR_1(name) //! Implement operator<< on class name, assuming it has two template arguments /** \copydetails RMF_OUTPUT_OPERATOR */ #define RMF_OUTPUT_OPERATOR_2(name) //! Implement operator<< on class name /** The class named should define the method \c void \c show(std::ostream&). */ #define RMF_OUTPUT_OPERATOR(name) //! Implement operator<< on class name templated by the dimension /** The class named should define the method \c void \c show(std::ostream&). */ #define RMF_OUTPUT_OPERATOR_D(name) //! Implement a hash function for the class #define RMF_HASHABLE_INLINE(name, hashret) /** @} */ #else #define RMF_SHOWABLE(Name) \ void show(std::ostream &out=std::cout) const; \ RMF_REQUIRE_SEMICOLON_CLASS(showable) #define RMF_SHOWABLE_INLINE(Name, how_to_show) \ void show(std::ostream &out=std::cout) const{ \ how_to_show; \ } \ RMF_REQUIRE_SEMICOLON_CLASS(showable) #define RMF_HASHABLE_INLINE(name, hashret)\ std::size_t __hash__() const { \ hashret; \ } #if !defined(SWIG) #define RMF_OUTPUT_OPERATOR_1(name) \ template \ inline std::ostream& operator<<(std::ostream &out, const name &i) \ { \ i.show(out); \ return out; \ } \ RMF_REQUIRE_SEMICOLON_NAMESPACE #define RMF_OUTPUT_OPERATOR_2(name) \ template \ inline std::ostream& operator<<(std::ostream &out, const name &i) \ { \ i.show(out); \ return out; \ } \ RMF_REQUIRE_SEMICOLON_NAMESPACE #define RMF_OUTPUT_OPERATOR(name) \ inline std::ostream &operator<<(std::ostream &out, const name &i) \ { \ i.show(out); \ return out; \ } \ RMF_REQUIRE_SEMICOLON_NAMESPACE #define RMF_OUTPUT_OPERATOR_D(name) \ template < int D> \ inline std::ostream &operator<<(std::ostream &out, const name &i) \ { \ i.show(out); \ return out; \ } \ RMF_REQUIRE_SEMICOLON_NAMESPACE #define RMF_OUTPUT_OPERATOR_UD(name) \ template \ inline std::ostream &operator<<(std::ostream &out, const name &i) \ { \ i.show(out); \ return out; \ } \ RMF_REQUIRE_SEMICOLON_NAMESPACE #else #define RMF_OUTPUT_OPERATOR_1(name) #define RMF_OUTPUT_OPERATOR_2(name) #define RMF_OUTPUT_OPERATOR(name) #define RMF_OUTPUT_OPERATOR_D(name) #define RMF_OUTPUT_OPERATOR_UD(name) #endif #endif /** @} */ //! Declare a RAII-style class /** Since such classes are typically quite small and simple, all the implementation is inline. The macro declares - default constructor - RAII::set() - RAII::reset() - destructor The Set and Reset arguments are the code to run in the respective functions. "args" are the argument string (in parens) for the constructor and set. */ #define RMF_RAII(Name, args, Initialize, Set, Reset, Show) \ Name() {Initialize;} \ explicit Name args {Initialize; Set;} \ void set args {reset(); \ Set;} \ void reset() {Reset;} \ ~Name () {reset();} \ RMF_SHOWABLE_INLINE(Name, out << #Name << '('; Show; out << ')'); \ private: \ void operator=(const Name &){} \ Name(const Name &){} \ public: \ RMF_REQUIRE_SEMICOLON_CLASS(raii) //! @} #endif /* RMF_MACROS_H */