UDK 3.2.7 C/C++ API Reference
|
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 00002 /* 00003 * Version: MPL 1.1 / GPLv3+ / LGPLv3+ 00004 * 00005 * The contents of this file are subject to the Mozilla Public License Version 00006 * 1.1 (the "License"); you may not use this file except in compliance with 00007 * the License or as specified alternatively below. You may obtain a copy of 00008 * the License at http://www.mozilla.org/MPL/ 00009 * 00010 * Software distributed under the License is distributed on an "AS IS" basis, 00011 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 00012 * for the specific language governing rights and limitations under the 00013 * License. 00014 * 00015 * Major Contributor(s): 00016 * [ Copyright (C) 2012 Lubos Lunak <l.lunak@suse.cz> (initial developer) ] 00017 * 00018 * All Rights Reserved. 00019 * 00020 * For minor contributions see the git repository. 00021 * 00022 * Alternatively, the contents of this file may be used under the terms of 00023 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or 00024 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), 00025 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable 00026 * instead of those above. 00027 */ 00028 00029 #ifndef _RTL_STRINGUTILS_HXX_ 00030 #define _RTL_STRINGUTILS_HXX_ 00031 00032 #include "sal/config.h" 00033 00034 // The unittest uses slightly different code to help check that the proper 00035 // calls are made. The class is put into a different namespace to make 00036 // sure the compiler generates a different (if generating also non-inline) 00037 // copy of the function and does not merge them together. The class 00038 // is "brought" into the proper rtl namespace by a typedef below. 00039 #ifdef RTL_STRING_UNITTEST 00040 #define rtl rtlunittest 00041 #endif 00042 00043 namespace rtl 00044 { 00045 00046 #ifdef RTL_STRING_UNITTEST 00047 #undef rtl 00048 #endif 00049 namespace internal 00050 { 00051 /* 00052 These templates use SFINAE (Substitution failure is not an error) to help distinguish the various 00053 plain C string types: char*, const char*, char[N], const char[N], char[] and const char[]. 00054 There are 2 cases: 00055 1) Only string literal (i.e. const char[N]) is wanted, not any of the others. 00056 In this case it is necessary to distinguish between const char[N] and char[N], as the latter 00057 would be automatically converted to the const variant, which is not wanted (not a string literal 00058 with known size of the content). In this case ConstCharArrayDetector is used to ensure the function 00059 is called only with const char[N] arguments. There's no other plain C string type overload. 00060 2) All plain C string types are wanted, and const char[N] needs to be handled differently. 00061 In this case const char[N] would match const char* argument type (not exactly sure why, but it's 00062 consistent in all of gcc, clang and msvc). Using a template with a reference to const of the type 00063 avoids this problem, and CharPtrDetector ensures that the function is called only with char pointer 00064 arguments. The const in the argument is necessary to handle the case when something is explicitly 00065 cast to const char*. Additionally (non-const) char[N] needs to be handled, but with the reference 00066 being const, it would also match const char[N], so another overload with a reference to non-const 00067 and NonConstCharArrayDetector are used to ensure the function is called only with (non-const) char[N]. 00068 Additionally, char[] and const char[] (i.e. size unknown) are rather tricky. Their usage with 'T&' would 00069 mean it would be 'char(&)[]', which seems to be invalid. But gcc and clang somehow manage when it is 00070 a template. while msvc complains about no conversion from char[] to char[1]. And the reference cannot 00071 be avoided, because 'const char[]' as argument type would match also 'const char[N]' 00072 So char[] and const char[] should always be used with their contents specified (which automatically 00073 turns them into char[N] or const char[N]), or char* and const char* should be used. 00074 */ 00075 struct Dummy {}; 00076 template< typename T1, typename T2 > 00077 struct CharPtrDetector 00078 { 00079 }; 00080 template< typename T > 00081 struct CharPtrDetector< const char*, T > 00082 { 00083 typedef T Type; 00084 }; 00085 template< typename T > 00086 struct CharPtrDetector< char*, T > 00087 { 00088 typedef T Type; 00089 }; 00090 00091 template< typename T1, typename T2 > 00092 struct NonConstCharArrayDetector 00093 { 00094 }; 00095 template< typename T, int N > 00096 struct NonConstCharArrayDetector< char[ N ], T > 00097 { 00098 typedef T Type; 00099 }; 00100 #ifdef RTL_STRING_UNITTEST 00101 // never use, until all compilers handle this 00102 template< typename T > 00103 struct NonConstCharArrayDetector< char[], T > 00104 { 00105 typedef T Type; 00106 }; 00107 template< typename T > 00108 struct NonConstCharArrayDetector< const char[], T > 00109 { 00110 typedef T Type; 00111 }; 00112 #endif 00113 00114 template< typename T1, typename T2 > 00115 struct ConstCharArrayDetector 00116 { 00117 }; 00118 template< int N, typename T > 00119 struct ConstCharArrayDetector< const char[ N ], T > 00120 { 00121 typedef T Type; 00122 static const int size = N; 00123 }; 00124 00125 // this one is used to rule out only const char[N] 00126 template< typename T > 00127 struct ExceptConstCharArrayDetector 00128 { 00129 typedef Dummy Type; 00130 }; 00131 template< int N > 00132 struct ExceptConstCharArrayDetector< const char[ N ] > 00133 { 00134 }; 00135 // this one is used to rule out only const char[N] 00136 // (const will be brought in by 'const T&' in the function call) 00137 // msvc needs const char[N] here (not sure whether gcc or msvc 00138 // are right, it doesn't matter). 00139 template< typename T > 00140 struct ExceptCharArrayDetector 00141 { 00142 typedef Dummy Type; 00143 }; 00144 template< int N > 00145 struct ExceptCharArrayDetector< char[ N ] > 00146 { 00147 }; 00148 template< int N > 00149 struct ExceptCharArrayDetector< const char[ N ] > 00150 { 00151 }; 00152 00153 } /* Namespace */ 00154 00155 } /* Namespace */ 00156 00157 #endif /* _RTL_STRINGUTILS_HXX_ */ 00158 00159 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */