Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2012-2023 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>
100 5400 : MatrixSquareBracketsAccess<T,C,I,J>::Const_row::Const_row(const MatrixSquareBracketsAccess&t,I i):
101 5400 : t(t),i(i) {}
102 :
103 : template<class T,class C,class I,class J>
104 82566119 : MatrixSquareBracketsAccess<T,C,I,J>::Row::Row(MatrixSquareBracketsAccess&t,I i):
105 82566119 : t(t),i(i) {}
106 :
107 : template<class T,class C,class I,class J>
108 5400 : 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 5400 : return (*static_cast<const T*>(&t))(i,j);
113 : }
114 :
115 : template<class T,class C,class I,class J>
116 82566119 : C & MatrixSquareBracketsAccess<T,C,I,J>::Row::operator[] (J j) {
117 : // This appears as a reference to a temporary object
118 : // however, in reality we know it is a reference to an object that is stored in the
119 : // t object. We thus suppress the warning raised by cppcheck
120 82566119 : return (*static_cast<T*>(&t))(i,j);
121 : }
122 :
123 : template<class T,class C,class I,class J>
124 82566119 : typename MatrixSquareBracketsAccess<T,C,I,J>::Row MatrixSquareBracketsAccess<T,C,I,J>::operator[] (I i) {
125 82566119 : return Row(*this,i);
126 : }
127 :
128 : template<class T,class C,class I,class J>
129 5400 : typename MatrixSquareBracketsAccess<T,C,I,J>::Const_row MatrixSquareBracketsAccess<T,C,I,J>::operator[] (I i)const {
130 5400 : return Const_row(*this,i);
131 : }
132 :
133 : }
134 :
135 :
136 : #endif
137 :
138 :
|