1 /*
2  * Tiny Vector Matrix Library
3  * Dense Vector Matrix Libary of Tiny size using Expression Templates
4  *
5  * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.net>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * $Id: CommaInitializer.h,v 1.18 2007-06-23 15:58:58 opetzold Exp $
22  */
23 
24 #ifndef TVMET_COMMA_INITIALIZER_H
25 #define TVMET_COMMA_INITIALIZER_H
26 
27 #include <tvmet/CompileTimeError.h>
28 
29 namespace tvmet {
30 
31 
32 /**
33  * \class CommaInitializer CommaInitializer.h "tvmet/CommaInitializer.h"
34  * \brief Initialize classes using a comma separated lists.
35  *
36  * The comma operator is called when it appears next to an object of
37  * the type the comma is defined for. However, "operator," is not called
38  * for function argument lists, only for objects that are out in the open,
39  * separated by commas (Thinking C++
40  * <a href=http://www.ida.liu.se/~TDDA14/online/v1ticpp/Chapter12.html>
41  * Ch.12: Operator comma</a>).
42  *
43  * This implementation uses the same technique as described in Todd Veldhuizen
44  * Techniques for Scientific C++
45  * <a href=http://extreme.indiana.edu/~tveldhui/papers/techniques/techniques01.html#l43>
46  * chapter 1.11 Comma overloading</a>.
47  *
48  * The initializer list is avaible after instanciation of the object,
49  * therefore use it like:
50  * \code
51  * vector3d t;
52  * t = 1.0, 2.0, 3.0;
53  * \endcode
54  * It's evaluated to (((t = 1.0), 2.0), 3.0)
55  *
56  * For matrizes the initilization is done row wise.
57  *
58  * If the comma separted list of values longer then the size of the vector
59  * or matrix a compile time error will occour. Otherwise the pending values
60  * will be written random into the memory.
61  *
62  */
63 template<class Obj, std::size_t LEN>
64 class CommaInitializer
65 {
66   CommaInitializer();
67   CommaInitializer& operator=(const CommaInitializer&);
68 
69 private:
70   /**
71    * \class Initializer
72    * \brief Helper fo recursive overloaded comma operator.
73    */
74   template<class T, std::size_t N> class Initializer
75   {
76     Initializer();
77     Initializer& operator=(const Initializer&);
78 
79   public:
80     typedef T						value_type;
81     typedef T*						iterator;
82 
83   public:
Initializer(iterator iter)84     Initializer(iterator iter) : m_iter(iter) { }
85 
86     /** Overloads the comma operator for recursive assign values from comma
87 	separated list. */
88     Initializer<value_type, N+1> operator,(value_type rhs)
89     {
90       TVMET_CT_CONDITION(N < LEN, CommaInitializerList_is_too_long)
91       *m_iter = rhs;
92       return Initializer<value_type, N+1>(m_iter + 1);
93     }
94 
95   private:
96     iterator 						m_iter;
97   };
98 
99 public:
100   typedef typename Obj::value_type 			value_type;
101   typedef value_type*					iterator;
102 
103 public:
CommaInitializer(const CommaInitializer & rhs)104   CommaInitializer(const CommaInitializer& rhs)
105     : m_object(rhs.m_object),
106       m_data(rhs.m_data),
107       m_wipeout_on_destruct(true)
108   {
109     rhs.disable();
110   }
111 
112   /** Constructor used by Vector or Matrix operator(value_type rhs) */
CommaInitializer(Obj & obj,value_type x)113   CommaInitializer(Obj& obj, value_type x)
114     : m_object(obj),
115       m_data(x),
116       m_wipeout_on_destruct(true)
117   { }
118 
119   /** Destructs and assigns the comma separated value. */
~CommaInitializer()120   ~CommaInitializer() {
121     if(m_wipeout_on_destruct) m_object.assign_value(m_data);
122   }
123 
124   /** Overloaded comma operator, called only once for the first occoured comma. This
125       means the first value is assigned by %operator=() and the 2nd value after the
126       comma. Therfore we call the %Initializer::operator,() for the list starting
127       after the 2nd. */
128   Initializer<value_type, 2> operator,(value_type rhs);
129 
disable()130   void disable() const { m_wipeout_on_destruct = false; }
131 
132 private:
133   Obj& 							m_object;
134   value_type 						m_data;
135   mutable bool 						m_wipeout_on_destruct;
136 };
137 
138 
139 /*
140  * Implementation
141  */
142 template<class Obj, std::size_t LEN>
143 typename CommaInitializer<Obj, LEN>::template Initializer<typename Obj::value_type, 2>
144 CommaInitializer<Obj, LEN>::operator,(typename Obj::value_type rhs)
145 {
146   m_wipeout_on_destruct = false;
147   iterator iter1 = m_object.data();
148   *iter1         = m_data;
149   iterator iter2 = iter1 + 1;
150   *iter2         = rhs;
151   return Initializer<value_type, 2>(iter2 + 1);
152 }
153 
154 
155 
156 } // namespace tvmet
157 
158 
159 #endif //  TVMET_COMMA_INITIALIZER_H
160 
161 // Local Variables:
162 // mode:C++
163 // tab-width:8
164 // End:
165