1

The Problem

Consider the following vectors:

std::vector<std::string> extensions;

extensions.push_back(".cpp");
extensions.push_back(".CPP");
extensions.push_back(".h");
extensions.push_back(".H");

std::vector<std::string> caselessUniqueExtensions;

Copy the contents of extensions into caselessUniqueExtensions, but discard all unique extensions, ignoring case. (I.e. the result should have two elements - one of either .cpp or .CPP, and one of either .h and .H.)

The Question

There are obviously many ways to do this, some more effecient than others, and some more readable than others. One such way I thought may work is the following:

#include <boost/algorithm/string/compare.hpp>

...

std::unique_copy(
  extensions.begin(), extensions.end(),
  caselessUniqueExts.begin(),
  boost::is_iequal());

However, it fails to compile using MSVS2010:

1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocale(626): error C2440: 'type cast' : cannot convert from 'unsigned char' to 'std::basic_string<_Elem,_Traits,_Ax>'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          No constructor could take the source type, or constructor overload resolution was ambiguous
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocale(2211) : see reference to function template instantiation '_Elem std::_Maklocchr<_Elem>(char,_Elem *,const std::_Locinfo::_Cvtvec &)' being compiled
1>          with
1>          [
1>              _Elem=std::basic_string<char,std::char_traits<char>,std::allocator<char>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocale(2210) : while compiling class template member function 'std::basic_string<_Elem,_Traits,_Ax> std::ctype<std::basic_string<_Elem,_Traits,_Ax>>::do_widen(char) const'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\locale(261) : see reference to class template instantiation 'std::ctype<_Elem>' being compiled
1>          with
1>          [
1>              _Elem=std::basic_string<char,std::char_traits<char>,std::allocator<char>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\locale(259) : see reference to function template instantiation '_Elem std::toupper<T1>(_Elem,const std::locale &)' being compiled
1>          with
1>          [
1>              _Elem=std::basic_string<char,std::char_traits<char>,std::allocator<char>>,
1>              T1=std::basic_string<char,std::char_traits<char>,std::allocator<char>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(2042) : see reference to function template instantiation 'bool boost::algorithm::is_iequal::operator ()<std::basic_string<_Elem,_Traits,_Ax>,std::basic_string<_Elem,_Traits,_Ax>>(const T1 &,const T2 &) const' being compiled
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>,
1>              T1=std::basic_string<char,std::char_traits<char>,std::allocator<char>>,
1>              T2=std::basic_string<char,std::char_traits<char>,std::allocator<char>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(2070) : see reference to function template instantiation '_OutIt std::_Unique_copy<_InIt,_OutIt,_Pr>(_FwdIt,_FwdIt,_OutIt,_Pr,std::forward_iterator_tag)' being compiled
1>          with
1>          [
1>              _OutIt=std::_Vector_iterator<std::_Vector_val<std::string,std::allocator<std::string>>>,
1>              _InIt=std::basic_string<char,std::char_traits<char>,std::allocator<char>> *,
1>              _Pr=boost::algorithm::is_iequal,
1>              _FwdIt=std::basic_string<char,std::char_traits<char>,std::allocator<char>> *
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(2094) : see reference to function template instantiation '_OutIt std::_Unique_copy1<std::basic_string<_Elem,_Traits,_Ax>*,_OutIt,_Pr>(_InIt,_InIt,_OutIt,_Pr,std::tr1::true_type)' being compiled
1>          with
1>          [
1>              _OutIt=std::_Vector_iterator<std::_Vector_val<std::string,std::allocator<std::string>>>,
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>,
1>              _Pr=boost::algorithm::is_iequal,
1>              _InIt=std::basic_string<char,std::char_traits<char>,std::allocator<char>> *
1>          ]
1>          c:\users\stv04463\documents\visual studio 2010\projects\pgp sandbox\pgp sandbox\main.cpp(64) : see reference to function template instantiation '_OutIt std::unique_copy<std::_Vector_iterator<_Myvec>,std::_Vector_iterator<_Myvec>,boost::algorithm::is_iequal>(_InIt,_InIt,_OutIt,_Pr)' being compiled
1>          with
1>          [
1>              _OutIt=std::_Vector_iterator<std::_Vector_val<std::string,std::allocator<std::string>>>,
1>              _Myvec=std::_Vector_val<std::string,std::allocator<std::string>>,
1>              _InIt=std::_Vector_iterator<std::_Vector_val<std::string,std::allocator<std::string>>>,
1>              _Pr=boost::algorithm::is_iequal
1>          ]
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocale(593): error C2440: 'type cast' : cannot convert from 'std::basic_string<_Elem,_Traits,_Ax>' to 'unsigned char'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocale(2229) : see reference to function template instantiation 'char std::_Maklocbyte<std::basic_string<_Elem,_Traits,_Ax>>(std::basic_string<_Elem,_Traits,_Ax>,const std::_Locinfo::_Cvtvec &)' being compiled
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocale(2225) : while compiling class template member function 'char std::ctype<_Elem>::_Donarrow(_Elem,char) const'
1>          with
1>          [
1>              _Elem=std::basic_string<char,std::char_traits<char>,std::allocator<char>>
1>          ]

Am I missing some basic understanding here, or should it not be possible to combine std::unique_copy with boost::is_iequal?

I am aware of the alternatives - I'd like to know why I'm getting this compiler error.

8
  • Can't you use std::set instead? With one set having a case insensitive compare function? Commented Jun 20, 2012 at 8:56
  • Note: Compiles fine with gcc 4.7. Commented Jun 20, 2012 at 8:59
  • I 've never used boost::is_iequal, but the documentation for is_equal sounds troubling. At least it gives me the impression that it tries to cast the arguments to unsigned char and compare for case-insensitive equality based on the locale using ==. Commented Jun 20, 2012 at 8:59
  • @JoachimPileborg - Yep, I could, there are many other alternatives too. But I'd like to understand why this doesn't work if at all possible. Commented Jun 20, 2012 at 9:02
  • 1
    @JimmidyJoo: Because it wouldn't work on std::string. But really, it's me who is uninitiated here. It's perfectly possible that I totally got the wrong picture (plus, I didn't read the source). Commented Jun 20, 2012 at 9:06

1 Answer 1

2

The boost::is_iequal predicate is meant to be used on single characters, not on an entire string like you're doing.

Unfortunately the Boost String Algorithms documentation is not the best, but you can see this specified here: "Defines element comparison predicates", where "element" refers to the string characters.

Internally, boost::is_iequal calls std::toupper on its arguments, and this can only work on characters.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.