我正在尝试编写类似std::for_each
的函数,除了正常用法之外,还可以使用std::function<bool (param)>
。错误的返回值意味着我想要摆脱循环。下面的代码是我到目前为止所获得的代码。
在评估!visitor(i)时,对a.visit([&](int) -> void)
的第二次调用无法编译。是否有可能使这项工作或我咆哮错误的树?
我正在使用MSVC 2010,但希望代码通常与C ++ 11兼容。
#include <list>
#include <string>
#include <iostream>
struct A
{
std::list<int> _lst;
template<typename _F>
void visit(_F visitor)
{
for(std::list<int>::const_iterator it = _lst.begin(), end = _lst.end() ; it != end ; it++) {
int i = *it;
if (std::is_void<decltype(visitor(i))>::value) {
visitor(i);
} else {
if (!visitor(i)) { // <----- error C2171: '!' : illegal on operands of type 'void'
break;
}
}
}
}
};
int main(int argc, char* argv[])
{
A a;
// populate a
for (int i = 0 ; i < 10 ; i++) {
a._lst.push_back(i);
}
a.visit([](int i) -> bool {
std::cout << i << std::endl;
return i < 5;
});
a.visit([](int i) {
std::cout << i << std::endl;
});
}
答案 0 :(得分:6)
以下是我将如何实施for_almost_each
;为了便于阅读,我using namespace std
加了类型别名。
#include <algorithm>
#include <iterator>
#include <functional>
using namespace std;
template<class Iter, class Func>
Iter
for_almost_each_impl(Iter begin, Iter end, Func func, std::true_type)
{
for (auto i = begin; i!=end; ++i)
if (!func(*i))
return i;
return end;
}
template<class Iter, class Func>
Iter
for_almost_each_impl(Iter begin, Iter end, Func func, std::false_type)
{
for_each(begin, end, func);
return end;
}
template<class Iter, class Func>
Iter for_almost_each(Iter begin, Iter end, Func func)
{
using Val = typename iterator_traits<Iter>::value_type;
using Res = typename result_of<Func(Val)>::type;
return for_almost_each_impl(begin, end,
func,
is_convertible<Res, bool>{} );
}
我使用is_convertible
,因为它似乎比is_same
更有意义。
答案 1 :(得分:4)
你的std :: is_void需要在编译时完成,不能在函数体内完成。这种函数重载的使用将起作用:
#include <list>
#include <string>
#include <iostream>
#include <type_traits> // missing header
struct A
{
std::list<int> _lst;
// wrapper for bool returning visitor
template<typename _F, typename Iter>
bool do_visit(_F visitor, Iter it, std::true_type)
{
return visitor(*it);
}
// wrapper for non-bool returning visitor
template<typename _F, typename Iter>
bool do_visit(_F visitor, Iter it, std::false_type)
{
visitor(*it);
return true;
}
template<typename _F>
void visit(_F visitor)
{
for (auto it = _lst.begin(), end = _lst.end() ; it != end ; it++) {
// select correct visitor wrapper function using overloading
if (!do_visit(visitor, it, std::is_same<bool, decltype(visitor(0))>())) {
break;
}
}
}
};
int main(int argc, char* argv[])
{
A a;
// populate a
for (int i = 0 ; i < 10 ; i++) {
a._lst.push_back(i);
}
a.visit([](int i) -> bool {
std::cout << i << std::endl;
return i < 5;
});
a.visit([](int i) {
std::cout << i << std::endl;
});
}
答案 2 :(得分:-1)
这个lambda没有返回一个值,这就是为什么你会得到一个&#34; visitor&#34;正在回归无效:
a.visit([](int i) {
std::cout << i << std::endl;
});
你可以通过重写为:
来完成这项工作a.visit([](int i) -> bool {
std::cout << i << std::endl;
return true;
});