including gtest.h 如何打破 std 算法的模板参数推导?
How does including gtest.h break template argument deduction for a std algorithm?
我升级到最新版本的 Google 测试,我的几个测试不再编译。我已将其简化为:
#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;
}
带有 /std:c++latest
的 Visual Studio 2019 (16.10.4) 编译器抱怨:
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'
如果我注释掉包含的 gtest.h,代码会正确构建和执行。
gtest.h 可能会做些什么来扰乱仅取决于 std
定义的类型和函数的调用的模板参数推导?
[注意,我的问题不是如何解决问题,而是了解具体的根本原因。我有一个解决方法:用 lambda 替换 std::isupper
。]
看来 <gtest/gtest.h>
现在包括 <locale>
,这引入了
template< class charT > bool isupper( charT ch, const locale& loc )
进入范围。这意味着 std::isupper
现在有两个可能指向的函数,如果您不指定要使用哪个函数,就会出现歧义,导致模板参数推导失败。
如果您确实采用 lambda 路径来解决此问题,请确保将 std::isupper
的输入转换为 unsigned char
之类的
const auto uppers = std::count_if(foo.begin(),
foo.end(),
[]()(auto ch){ return std::isupper(static_cast<unsigned char>(ch));} )
我升级到最新版本的 Google 测试,我的几个测试不再编译。我已将其简化为:
#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;
}
带有 /std:c++latest
的 Visual Studio 2019 (16.10.4) 编译器抱怨:
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'
如果我注释掉包含的 gtest.h,代码会正确构建和执行。
gtest.h 可能会做些什么来扰乱仅取决于 std
定义的类型和函数的调用的模板参数推导?
[注意,我的问题不是如何解决问题,而是了解具体的根本原因。我有一个解决方法:用 lambda 替换 std::isupper
。]
看来 <gtest/gtest.h>
现在包括 <locale>
,这引入了
template< class charT > bool isupper( charT ch, const locale& loc )
进入范围。这意味着 std::isupper
现在有两个可能指向的函数,如果您不指定要使用哪个函数,就会出现歧义,导致模板参数推导失败。
如果您确实采用 lambda 路径来解决此问题,请确保将 std::isupper
的输入转换为 unsigned char
之类的
const auto uppers = std::count_if(foo.begin(),
foo.end(),
[]()(auto ch){ return std::isupper(static_cast<unsigned char>(ch));} )