IMP logo
IMP Reference Guide  2.18.0
The Integrative Modeling Platform
bracket_macros.h
Go to the documentation of this file.
1 /**
2  * \file IMP/bracket_macros.h
3  * \brief Macros to handle array indexing.
4  *
5  * Copyright 2007-2022 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPKERNEL_BRACKET_MACROS_H
10 #define IMPKERNEL_BRACKET_MACROS_H
11 #include <IMP/kernel_config.h>
12 
13 #ifdef IMP_DOXYGEN
14 //! Implement operator[] and at() for C++, and __getitem__ for Python.
15 /** The index type is Index and the expression that returns the value is expr.
16  Like the equivalent methods in std::vector, at() performs bound checking;
17  if the bounds_check_expr is false, then a UsageException is thrown.
18  operator[] does no bounds checks, except in debug mode. In Python, bounds
19  checking is always done and results in an IndexException if
20  bounds_check_expr is false.
21 */
22 #define IMP_BRACKET(Value, Index, bounds_check_expr, expr) \
23  const Value at(Index) const; \
24  Value& at(Index); \
25  const Value operator[](Index) const; \
26  Value& operator[](Index);
27 
28 //! Implement operator[] and at() for C++, and __getitem__ for Python.
29 /** The index type is Index and the expression that returns the value is expr.
30  The value returned is not mutable.
31  Like the equivalent methods in std::vector, at() performs bound checking;
32  if the bounds_check_expr is false, then a UsageException is thrown.
33  operator[] does no bounds checks, except in debug mode. In Python, bounds
34  checking is always done and results in an IndexException if
35  bounds_check_expr is false.
36 */
37 #define IMP_CONST_BRACKET(Value, Index, bounds_check_expr, expr) \
38  const Value at(Index) const; \
39  const Value operator[](Index) const;
40 
41 #elif !defined(SWIG)
42 #define IMP_CONST_BRACKET(Value, Index, bounds_check_expr, expr) \
43  const Value& operator[](Index i) const { \
44  IMP_INTERNAL_CHECK((bounds_check_expr), "Index out of range: " << i); \
45  expr; \
46  } \
47  const Value& at(Index i) const { \
48  IMP_USAGE_CHECK((bounds_check_expr), "Index out of range: " << i); \
49  expr; \
50  } \
51  const Value& __getitem__(Index i) const { \
52  if (!(bounds_check_expr)) { \
53  IMP_THROW("Bad index " << i, IMP::IndexException); \
54  } \
55  expr; \
56  }
57 
58 #define IMP_BRACKET(Value, Index, bounds_check_expr, expr) \
59  Value& at(Index i) { \
60  IMP_USAGE_CHECK((bounds_check_expr), "Index out of range: " << i); \
61  expr; \
62  } \
63  Value& operator[](Index i) { \
64  IMP_INTERNAL_CHECK((bounds_check_expr), "Index out of range: " << i); \
65  expr; \
66  } \
67  void __setitem__(Index i, const Value& v) { at(i) = v; } \
68  IMP_CONST_BRACKET(Value, Index, bounds_check_expr, expr)
69 
70 #else
71 #define IMP_CONST_BRACKET(Value, Index, bounds_check_expr, expr) \
72  const Value& __getitem__(Index i) const { \
73  if (!(bounds_check_expr)) { \
74  IMP_THROW("Bad index " << i, IMP::IndexException); \
75  } \
76  expr; \
77  }
78 
79 #define IMP_BRACKET(Value, Index, bounds_check_expr, expr) \
80  void __setitem__(Index i, const Value& v) { at(i) = v; } \
81  IMP_CONST_BRACKET(Value, Index, bounds_check_expr, expr)
82 
83 #endif
84 
85 #endif /* IMPKERNEL_BRACKET_MACROS_H */