我有一个向量的向量,我想检查它们是否都是空的。使用标准库,我尝试了:
#include <algorithm>
#include <vector>
int main()
{
std::vector<std::vector<int>> vv;
std::all_of(std::begin(vv), std::end(vv), std::empty);
}
这导致clang 7.0:
的/ usr / bin中/../ LIB / GCC / x86_64的-Linux的GNU / 6.3.0 /../../../../包括/ C ++ / 6.3.0 /比特/ stl_algo.h :508:5: 注意:候选模板被忽略:无法推断模板参数 &#39; _Predicate&#39;
由于类型演绎的规则,我认为这是一种标准行为。但无论如何,我最简单的解决方法是什么?
编辑:我接受了rubenvb的回答,因为他给出了一个简单而合理的解释,以及自然的解决方法。 all_of接受谓词,谓词是函数,函数对象或lambda表达式。 std :: empty既不是那些,也不是函数模板。当显式实例化它时,我们得到一个应该工作的普通函数。令人惊讶的是,它仍然没有在我尝试的大多数编译器上编译。好吧,让我们看看:
在GCC 6.3上,编译得很好 - https://godbolt.org/g/Pxta7C
但是在来自主干的GCC上,它会导致内部编译器错误 - https://godbolt.org/g/H6DHt5
来自主干或2017年MSVC的Clang都没有成功编译它:
https://godbolt.org/g/819pbQ(Clang)
https://godbolt.org/g/ua5E8e(MSVC)
EDIT2:显然,Robert Andrzejuk也是对的:编译器无法处理它的原因是模糊的重载决策。 std :: empty有3个不同的重载。其中两个同样很好的候选者:一般的一个和std :: initializer列表一个。我使用以下最小版本获得了类似的结果:
#include <vector>
template<class T>
void foo(const T& t);
template<class T>
void foo(const std::initializer_list<T>& il);
template<class F>
void bar(F f);
int main()
{
bar(foo<std::vector<int>>);
}
但有一点不同。这个例子根本不能在GCC中从trunk编译(而不是导致ICE)。
答案 0 :(得分:2)
不幸的是,区分重载的模板函数存在问题,因为SmtpClient GenMailClient = new SmtpClient();
GenMailClient.Send(message);
也是模板函数。更好的解释:std::function fails to distinguish overloaded functions
为此,需要std::all_of
到正确的函数类型:static_cast
:
bool ( * )( const std::vector< int >& )
使用有关所需std::all_of( vv.begin(), vv.end(),
static_cast< bool ( * )( const std::vector< int >& ) >( std::empty ) );
的知识,我们可以创建一个帮助模板函数,从容器类型中推导出正确的定义:
辅助函数:
static_cast
它的用法示例:
template< typename C >
inline auto overloaded_pred_for( const C&, bool ( *f )( const C& ) ) -> decltype( f )
{
return f;
}
答案 1 :(得分:1)
快速解决方法
#include <algorithm>
#include <vector>
int main() {
std::vector<std::vector<int>> vv;
std::all_of(std::begin(vv), std::end(vv),
[](const auto &v) {return std::empty(v);});
}
答案 2 :(得分:1)
我最简单的解决方法是什么?
也许
std::all_of(std::begin(vv), std::end(vv),
[](auto const & v){ return v.empty(); });
答案 3 :(得分:1)
std::empty
is a function template,因此不是一个可调用的对象。通过显式提供模板参数,可以将函数模板名称转换为可调用的具体实例:
#include <algorithm>
#include <iterator>
#include <vector>
int main()
{
std::vector<std::vector<int>> vv;
std::all_of(std::begin(vv), std::end(vv), std::empty<std::vector<int>>);
}
Live demo (which incidentally crashes the compiler)。另请注意,此GCC版本显然需要#include <iterator>
,即使明确提到std::empty
也应该使用例如#include <vector>
。 ctrl + shift + r
...
答案 4 :(得分:-1)
问题是没有std :: empty这样的东西,据我所知,它是一个成员函数。尝试使用[](const auto& i){ return i.empty(); }
代替。
编辑: 好吧,我之前没有见过std :: empty但是正如下面的评论者指出它存在,但你仍然可以使用lambda