1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2    Copyright (c) 2012-2021 The plumed team
3    (see the PEOPLE file at the root of the distribution for a list of names)
4 
5    See http://www.plumed.org for more information.
6 
7    This file is part of plumed, version 2.
8 
9    plumed is free software: you can redistribute it and/or modify
10    it under the terms of the GNU Lesser General Public License as published by
11    the Free Software Foundation, either version 3 of the License, or
12    (at your option) any later version.
13 
14    plumed is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU Lesser General Public License for more details.
18 
19    You should have received a copy of the GNU Lesser General Public License
20    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
21 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 #ifndef __PLUMED_tools_MatrixSquareBracketsAccess_h
23 #define __PLUMED_tools_MatrixSquareBracketsAccess_h
24 
25 namespace PLMD {
26 
27 /**
28 Utility class to add [][] access
29 
30 \tparam T The type of the matrix class.
31 \tparam C The type of the returned value.
32 \tparam I The type of the first index (default unsigned).
33 \tparam J The type of the second index (default unsigned).
34 
35 It implements the trick described in C++ FAQ 13.12 to allow [][] access
36 to matrix-like classes, based on the (,) syntax, thus translating
37 [i][j] into (i,j).  In practice, one only needs to implement the (,) syntax and to inherit from
38 MatrixSquareBracketsAccess.
39 The first template parameter (T) should be the
40 class itself, the second (C) is the type of the returned value,
41 and the third (I) and fourth (J) are the types of the two indexes (unsigned by default).
42 As everything is inlined, no overhead is expected.
43 
44 \verbatim
45 
46 class MyMatrixClass:
47   public MatrixSquareBracketsAccess<MyMatrixClass,double>
48 {
49   double data[16];
50 public:
51   double & operator ()(unsigned i,unsigned j){
52     return data[4*i+j];
53   }
54   const double & operator ()(unsigned i,unsigned j)const{
55     return data[4*i+j];
56   }
57 };
58 
59 int main(){
60   MyMatrixClass m;
61   m[0][1]=3.0;
62   return 0;
63 }
64 \endverbatim
65 
66 */
67 
68 template<class T,class C,class I=unsigned,class J=unsigned>
69 class MatrixSquareBracketsAccess {
70 /// Small utility class which just contains a pointer to the T and the row number
71   class Const_row {
72     friend class MatrixSquareBracketsAccess; // this so as to allow only T to instantiate Const_row
73     // the user should not manipulate it directly
74     const MatrixSquareBracketsAccess& t;
75     const I i;
76     Const_row(const MatrixSquareBracketsAccess&t,I i); // constructor is private and cannot be manipulated by the user
77   public:
78     /// access element
79     const C & operator[] (J j)const;
80   };
81 /// Small utility class which just contains a pointer to the T and the row number
82   class Row {
83     friend class MatrixSquareBracketsAccess; // this so as to allow only T to instantiate Const_row
84     // the user should not manipulate it directly
85     MatrixSquareBracketsAccess& t;
86     const I i;
87     Row(MatrixSquareBracketsAccess&t,I i); // constructor is private and cannot be manipulated by the user
88   public:
89     /// access element
90     C & operator[] (J j);
91   };
92 public:
93 /// access element (with [][] syntax)
94   Row operator[] (I i);
95 /// access element (with [][] syntax)
96   Const_row operator[] (I i)const;
97 };
98 
99 template<class T,class C,class I,class J>
Const_row(const MatrixSquareBracketsAccess & t,I i)100 MatrixSquareBracketsAccess<T,C,I,J>::Const_row::Const_row(const MatrixSquareBracketsAccess&t,I i):
101   t(t),i(i) {}
102 
103 template<class T,class C,class I,class J>
Row(MatrixSquareBracketsAccess & t,I i)104 MatrixSquareBracketsAccess<T,C,I,J>::Row::Row(MatrixSquareBracketsAccess&t,I i):
105   t(t),i(i) {}
106 
107 template<class T,class C,class I,class J>
108 const C & MatrixSquareBracketsAccess<T,C,I,J>::Const_row::operator[] (J j)const {
109 // This appears as a reference to a temporary object
110 // however, in reality we know it is a reference to an object that is stored in the
111 // t object. We thus suppress the warning raised by cppcheck
112 // cppcheck-suppress returnTempReference
113   return (*static_cast<const T*>(&t))(i,j);
114 }
115 
116 template<class T,class C,class I,class J>
117 C & MatrixSquareBracketsAccess<T,C,I,J>::Row::operator[] (J j) {
118 // This appears as a reference to a temporary object
119 // however, in reality we know it is a reference to an object that is stored in the
120 // t object. We thus suppress the warning raised by cppcheck
121 // cppcheck-suppress returnTempReference
122   return (*static_cast<T*>(&t))(i,j);
123 }
124 
125 template<class T,class C,class I,class J>
126 typename MatrixSquareBracketsAccess<T,C,I,J>::Row MatrixSquareBracketsAccess<T,C,I,J>::operator[] (I i) {
127   return Row(*this,i);
128 }
129 
130 template<class T,class C,class I,class J>
131 typename MatrixSquareBracketsAccess<T,C,I,J>::Const_row MatrixSquareBracketsAccess<T,C,I,J>::operator[] (I i)const {
132   return Const_row(*this,i);
133 }
134 
135 }
136 
137 
138 #endif
139 
140 
141