Commits

nat_linden committed af93020

MAINT-1175: Ditch LLTypeInfoLookup, make map<const type_info*> work.
Instead of forbidding std::map<const std::type_info*, ...> outright (which
includes LLRegistry<const std::type_info*, ...> and LLRegistrySingleton<const
std::type_info*, ...>), try to make it work by specializing std::less<const
std::type_info*> to use std::type_info::before().
Make LLRegistryDefaultComparator<T> use std::less<T> so it can capitalize on
that specialization.

Comments (0)

Files changed (4)

indra/llcommon/llinitparam.h

 #include <boost/shared_ptr.hpp>
 
 #include "llerror.h"
-#include "lltypeinfolookup.h"
+#include "llstl.h"
 
 namespace LLInitParam
 {
 		typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
 		typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t;
 
-		typedef LLTypeInfoLookup<parser_read_func_t>		parser_read_func_map_t;
-		typedef LLTypeInfoLookup<parser_write_func_t>		parser_write_func_map_t;
-		typedef LLTypeInfoLookup<parser_inspect_func_t>		parser_inspect_func_map_t;
+		typedef std::map<const std::type_info*, parser_read_func_t>		parser_read_func_map_t;
+		typedef std::map<const std::type_info*, parser_write_func_t>	parser_write_func_map_t;
+		typedef std::map<const std::type_info*, parser_inspect_func_t>	parser_inspect_func_map_t;
 
 		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
 		:	mParseSilently(false),
 
 		template <typename T> bool readValue(T& param)
 	    {
-		    boost::optional<parser_read_func_t> found_it = mParserReadFuncs->find<T>();
-		    if (found_it)
+		    parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
+		    if (found_it != mParserReadFuncs->end())
 		    {
-			    return (*found_it)(*this, (void*)&param);
+			    return found_it->second(*this, (void*)&param);
 		    }
 		    return false;
 	    }
 
 		template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
 		{
-		    boost::optional<parser_write_func_t> found_it = mParserWriteFuncs->find<T>();
-		    if (found_it)
+		    parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
+		    if (found_it != mParserWriteFuncs->end())
 		    {
-			    return (*found_it)(*this, (const void*)&param, name_stack);
+			    return found_it->second(*this, (const void*)&param, name_stack);
 		    }
 		    return false;
 		}
 		// dispatch inspection to registered inspection functions, for each parameter in a param block
 		template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
 		{
-		    boost::optional<parser_inspect_func_t> found_it = mParserInspectFuncs->find<T>();
-		    if (found_it)
+		    parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
+		    if (found_it != mParserInspectFuncs->end())
 		    {
-			    (*found_it)(name_stack, min_count, max_count, possible_values);
+			    found_it->second(name_stack, min_count, max_count, possible_values);
 				return true;
 		    }
 			return false;
 		template <typename T>
 		void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
 		{
-			mParserReadFuncs->insert<T>(read_func);
-			mParserWriteFuncs->insert<T>(write_func);
+			mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
+			mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
 		}
 
 		template <typename T>
 		void registerInspectFunc(parser_inspect_func_t inspect_func)
 		{
-			mParserInspectFuncs->insert<T>(inspect_func);
+			mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
 		}
 
 		bool				mParseSilently;

indra/llcommon/llregistry.h

 
 #include <boost/type_traits.hpp>
 #include "llsingleton.h"
-#include "lltypeinfolookup.h"
+#include "llstl.h"
 
 template <typename T>
 struct LLRegistryDefaultComparator
 {
-	// It would be Bad if this comparison were used for const char*
-	BOOST_STATIC_ASSERT(! (boost::is_same<typename boost::remove_const<typename boost::remove_pointer<T>::type>::type, char>::value));
-	bool operator()(const T& lhs, const T& rhs) const { return lhs < rhs; }
-};
-
-// comparator for const char* registry keys
-template <>
-struct LLRegistryDefaultComparator<const char*>
-{
-	bool operator()(const char* lhs, const char* rhs) const
+	bool operator()(const T& lhs, const T& rhs) const
 	{
-		return strcmp(lhs, rhs) < 0;
+		using std::less;
+		return less<T>()(lhs, rhs);
 	}
 };
 
-template <typename KEY, typename VALUE>
-struct LLRegistryMapSelector
-{
-    typedef std::map<KEY, VALUE> type;
-};
-
-template <typename VALUE>
-struct LLRegistryMapSelector<std::type_info*, VALUE>
-{
-    typedef LLTypeInfoLookup<VALUE> type;
-};
-
-template <typename VALUE>
-struct LLRegistryMapSelector<const std::type_info*, VALUE>
-{
-    typedef LLTypeInfoLookup<VALUE> type;
-};
-
 template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
 class LLRegistry
 {

indra/llcommon/llstl.h

 #include <vector>
 #include <set>
 #include <deque>
+#include <typeinfo>
 
 // Use to compare the first element only of a pair
 // e.g. typedef std::set<std::pair<int, Data*>, compare_pair<int, Data*> > some_pair_set_t; 
   return llbinder2nd<_Operation>(__oper, _Arg2_type(__x));
 }
 
+/**
+ * Specialize std::less<std::type_info*> to use std::type_info::before().
+ * See MAINT-1175. It is NEVER a good idea to directly compare std::type_info*
+ * because, on Linux, you might get different std::type_info* pointers for the
+ * same type (from different load modules)!
+ */
+namespace std
+{
+    template <>
+    struct less<const std::type_info*>:
+        public std::binary_function<const std::type_info*, const std::type_info*, bool>
+    {
+        bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
+        {
+            return lhs->before(*rhs);
+        }
+    };
+
+    template <>
+    struct less<std::type_info*>:
+        public std::binary_function<std::type_info*, std::type_info*, bool>
+    {
+        bool operator()(std::type_info* lhs, std::type_info* rhs) const
+        {
+            return lhs->before(*rhs);
+        }
+    };
+} // std
+
 #endif // LL_LLSTL_H

indra/llui/lluictrlfactory.h

 #include "llinitparam.h"
 #include "llregistry.h"
 #include "llxuiparser.h"
+#include "llstl.h"
 
 class LLView;
 
 
 // lookup widget name by type
 class LLWidgetNameRegistry 
-:	public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry , LLCompareTypeID>
+:	public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry>
 {};
 
 // lookup function for generating empty param block by widget type
 // this is used for schema generation
 //typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();
 //class LLDefaultParamBlockRegistry
-//:	public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry, LLCompareTypeID>
+//:	public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry>
 //{};
 
 extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP;