lua++
C:/Documents and Settings/Kalith/My Documents/Programmation/luapp/include/luapp_var.hpp
Go to the documentation of this file.
00001 #ifndef LUAPP_VAR_H
00002 #define LUAPP_VAR_H
00003 
00004 #include "luapp_exception.hpp"
00005 #include <utils_refptr.hpp>
00006 #include <typeinfo>
00007 
00008 namespace lua
00009 {
00010 typedef std::type_info var_type;
00011 
00012 /// Base type : untyped variable
00013 /** The purpose of this class is to have an untyped
00014 *   return value / argument. It allows simple manipulation
00015 *   of events, and a lot of other things.<br><br>
00016 *   It uses a little bit more memory than a simple object :<br>
00017 *   sizeof(void*) + sizeof(T)<br>... and has the overhead of
00018 *   using the v-table (because of inheritance). At last, var
00019 *   does a dynamic_cast (which is not the fastest thing in the
00020 *   world) each time you call get().<br>
00021 *   So this class is definatly slower than base types : <b>use it
00022 *   wisely</b>.
00023 *   \note This class is highly inspired from boost::any.
00024 */
00025 class var
00026 {
00027 public :
00028 
00029     /// Default constructor.
00030     var();
00031 
00032     /// Value assignment constructor.
00033     /** \param mValue The value to assign
00034     */
00035     template <class T>
00036     var(const T& mValue) : pValue_(new value<T>(mValue)) {}
00037 
00038     /// Copy constructor.
00039     /** \param mVar The var to copy
00040     */
00041     var(const var& mVar);
00042 
00043     var& operator = (const var& mVar);
00044 
00045     bool operator == (const var& mVar) const;
00046 
00047     bool operator != (const var& mVar);
00048 
00049     /// Swaps this value with another.
00050     /** \param mVar the value to swap with this one
00051     */
00052     void swap(var& mVar);
00053 
00054     /// Returns the contained value.
00055     /** \return The contained value
00056     *   \note If the provided type doesn't match the
00057     *         contained value's, a Warning is printed
00058     *         in the log, and this function returns a
00059     *         default value.
00060     */
00061     template<class T>
00062     const T get() const
00063     {
00064         const value<T>* pValue = dynamic_cast<const value<T>*>(pValue_.get());
00065         if (pValue)
00066         {
00067             return pValue->mT_;
00068         }
00069         else
00070         {
00071             if (pValue_)
00072                 throw lua::exception("var",
00073                     "Conversion from type \""+std::string(pValue_->get_type().name())+
00074                     "\" to \""+typeid(T).name()+"\" failed. Returning default "
00075                     "value."
00076                 );
00077 
00078             return T();
00079         }
00080     }
00081 
00082     /// Checks if this variable is empty.
00083     /** \return 'true' if this variable is empty
00084     *   \note Only the default constructor of var returns
00085     *         an empty variable.
00086     */
00087     bool is_empty() const;
00088 
00089     /// Returns the type of the contained value.
00090     /** \return The type of the contained value
00091     *   \note Returns typeid(void) if the variable is empty.
00092     */
00093     const var_type& get_type() const;
00094 
00095     /// Checks the contained value's type.
00096     /** \return 'true' if the contained value's type is the one
00097     *           you provided
00098     */
00099     template<class T>
00100     bool is_of_type() const
00101     {
00102         if (pValue_)
00103         {
00104             return pValue_->get_type() == typeid(T);
00105         }
00106         else
00107         {
00108             return typeid(void) == typeid(T);
00109         }
00110     }
00111 
00112     /// Converts this variable to a string.
00113     /** \return This variable converted to a string
00114     */
00115     std::string to_string() const;
00116 
00117     static const var_type& VALUE_NONE;
00118     static const var_type& VALUE_INT;
00119     static const var_type& VALUE_UINT;
00120     static const var_type& VALUE_FLOAT;
00121     static const var_type& VALUE_DOUBLE;
00122     static const var_type& VALUE_BOOL;
00123     static const var_type& VALUE_STRING;
00124     static const var_type& VALUE_POINTER;
00125 
00126 private :
00127 
00128     /** \cond NOT_REMOVE_FROM_DOC
00129     */
00130 
00131     class value_base
00132     {
00133     public :
00134 
00135         virtual ~value_base() {}
00136         virtual value_base* clone() const = 0;
00137         virtual const var_type& get_type() const = 0;
00138     };
00139 
00140     template <class T>
00141     class value : public value_base
00142     {
00143     public :
00144 
00145         #ifdef MSVC
00146             // Note : Disable a false warning from Microsoft's Visual C++ :
00147             // "the inline specifier cannot be used when a friend declaration
00148             // refers to a specialization of a function template"
00149             #pragma warning( disable : 4396 )
00150         #endif
00151         friend const T var::get<>() const;
00152 
00153         value(const T& mT) : mT_(mT) {}
00154 
00155         value_base* clone() const
00156         {
00157             return new value(mT_);
00158         }
00159 
00160         const var_type& get_type() const
00161         {
00162             return typeid(T);
00163         }
00164 
00165     private :
00166 
00167         T mT_;
00168     };
00169 
00170     /** \endcond
00171     */
00172 
00173     utils::refptr<value_base> pValue_;
00174 };
00175 }
00176 
00177 #endif