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