I upgraded to the latest release of Google Test, and several of my tests no longer compiled. I've reduced it to this:
#include <gtest/gtest.h>
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
int main () {
const std::string foo = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const auto uppers = std::count_if(foo.begin(), foo.end(), std::isupper);
std::cout << "There are " << uppers << " capitals." << std::endl;
return 0;
}
The Visual Studio 2019 (16.10.4) compiler with /std:c++latest
complains:
1>Source.cpp(10,30): error C2672: 'std::count_if': no matching overloaded function found
1>Source.cpp(10,75): error C2780: 'conditional_t<std::_Is_from_primary<std::iterator_traits<remove_cv<remove_reference<_Ty2>::type>::type>>,std::incrementable_traits<remove_cv<remove_reference<_Ty2>::type>::type>,std::iterator_traits<remove_cv<remove_reference<_Ty2>::type>::type>>::difference_type std::count_if(_ExPo &&,const _FwdIt,const _FwdIt,_Pr) noexcept': expects 4 arguments - 3 provided
1>algorithm(570): message : see declaration of 'std::count_if'
1>Source.cpp(10,30): error C2783: 'conditional_t<std::_Is_from_primary<std::iterator_traits<remove_cv<remove_reference<_Ty>::type>::type>>,std::incrementable_traits<remove_cv<remove_reference<_Ty>::type>::type>,std::iterator_traits<remove_cv<remove_reference<_Ty>::type>::type>>::difference_type std::count_if(_InIt,_InIt,_Pr)': could not deduce template argument for '_Pr'
1>algorithm(553): message : see declaration of 'std::count_if'
If I comment out the inclusion of gtest.h, the code builds and executes correctly.
What could gtest.h be doing that messes up template argument deduction for a call that depends only on std
-defined types and functions?
[Note, my question is not how to workaround the problem, but to understand the specific underlying cause. I have a workaround: Replace the std::isupper
with a lambda.]
It appears that <gtest/gtest.h>
is now including <locale>
, which introduces
template< class charT > bool isupper( charT ch, const locale& loc )
into the scope. That means that std::isupper
now has two possible functions it could point to and without you specifying which one to use, you get an ambiguity which causes template argument deduction to fail.
If you do go the lambda route to fix this, make sure you cast the input to std::isupper
to an unsigned char
like
const auto uppers = std::count_if(foo.begin(),
foo.end(),
[]()(auto ch){ return std::isupper(static_cast<unsigned char>(ch));} )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With