> cout << strA << endl;
What about this:
#include <iostream>
#include <string>
#include <type_traits>
using namespace std;
template<typename Elem>
struct icase_traits : public char_traits<Elem>
{
using char_type = char_traits<Elem>::char_type;
private:
static constexpr Elem tolower( char_type c ) noexcept
{
return c < 'A' || c > 'Z' ? c : c - ('A' - 'a');
}
public:
static constexpr bool eq( char_type a, char_type b ) noexcept
{
return tolower( a ) == tolower( b );
}
static constexpr bool lt( char_type a, char_type b ) noexcept
{
return tolower( a ) < tolower( b );
}
static constexpr int compare( char_type const *s1, char_type const *s2,
size_t count )
{
for( size_t i = 0; i != count; ++i )
{
char_type
a = tolower( s1[i] ),
b = tolower( s2[i] );
if( a == b ) [[likely]]
continue;
if constexpr( is_integral_v<char_type> && sizeof(char_type) <
sizeof(int) )
return (int)a - (int)b;
else
return a < b ? -1 : 1;
}
return 0;
}
};
template<typename Elem, typename Alloc = allocator<Elem>>
using icase_string = basic_string<Elem, icase_traits<Elem>, Alloc>;
template<typename CharT, typename OTraits, typename Alloc>
basic_ostream<CharT, OTraits> &operator <<( basic_ostream<CharT,
OTraits> &str, icase_string<CharT, Alloc> const &out )
{
return str << out.c_str();
}
int main()
{
icase_string<char>
strA( "hello" ),
strB( "Hello" );
cout << (strA == strB) << endl;
cout << strA << endl;
}