我是“基于 lambda 的 foreach 循环”的粉丝:
class SomeDataStructure
{
private:
std::vector<SomeData> data;
public:
template<typename TF> void forData(TF mFn)
{
for(int i{0}; i < data.size(); ++i)
mFn(i, data[i]);
}
};
SomeDataStructure sds;
int main()
{
sds.forData([](auto idx, auto& data)
{
// ...
});
}
我认为它是更复杂数据结构的一个很好的抽象,因为它允许用户直观地循环使用附加参数的内容。编译器优化应保证性能与传统的 for(...) 循环相同。
不幸的是,像这样使用 lambda 显然会阻止使用有时有用的 continue; 和 break; 语句。
sds.forData([](auto idx, auto& data)
{
// Not valid!
if(data.isInvalid()) continue;
});
有没有什么方法可以模拟 continue; 和 break; 语句而不会有任何性能损失并且不会降低语法的便利性?
最佳答案
用产生迭代器的成员函数begin和end替换成员函数forData,然后替换
sds.forData([](auto idx, auto& data)
{
// Not valid!
if(data.isInvalid()) continue;
});
与
for( auto& data : sds )
{
if(data.isInvalid()) continue;
}
但是,如果出于某些未公开的原因您更愿意使用 forData 成员函数,那么您可以通过以下方式实现伪continue 和 break一些滥用异常。例如,Python 的 for 循环是基于异常的。 forData 驱动程序代码将忽略继续异常,并通过停止迭代来处理中断异常。
template<typename TF> void forData(TF mFn)
{
for(int i{0}; i < data.size(); ++i)
{
try
{
mFn(i, data[i]);
}
catch( const Continue& )
{}
catch( const Break& )
{
return;
}
}
}
另一种方法是要求 lambda 返回一个表示“break”或“continue”的值。
最自然的做法是为此使用枚举类型。
在我看来,返回值方法的主要问题是它劫持了 lambda 结果值,例如然后它不能(非常容易地)用于产生循环累积的结果,或类似的东西。
不过,我不会这样做。我宁愿使用基于范围的 for 循环,正如本答案开头所推荐的那样。但如果您这样做,并且担心效率,那么请记住要做的第一件事就是衡量。
你可以实现一个类似 Python 的枚举函数,它产生一个集合的逻辑 View ,这样集合看起来是(值,索引)对的集合,非常适合在基于范围的 for 循环:
cout << "Vector:" << endl;
vector<int> v = {100, 101, 102};
for( const auto e : enumerated( v ) )
{
cout << " " << e.item << " at " << e.index << endl;
}
以下代码(最低限度,只是为了这个答案而拼凑而成)显示了一种执行此操作的方法:
#include <functional> // std::reference_wrapper
#include <iterator> // std::begin, std::end
#include <utility> // std::declval
#include <stddef.h> // ptrdiff_t
#include <type_traits> // std::remove_reference
namespace cppx {
using Size = ptrdiff_t;
using Index = Size;
template< class Type > using Reference = std::reference_wrapper<Type>;
using std::begin;
using std::declval;
using std::end;
using std::ref;
using std::remove_reference;
template< class Derived >
struct Rel_ops_from_compare
{
friend
auto operator!=( const Derived& a, const Derived& b )
-> bool
{ return compare( a, b ) != 0; }
friend
auto operator<( const Derived& a, const Derived& b )
-> bool
{ return compare( a, b ) < 0; }
friend
auto operator<=( const Derived& a, const Derived& b )
-> bool
{ return compare( a, b ) <= 0; }
friend
auto operator==( const Derived& a, const Derived& b )
-> bool
{ return compare( a, b ) == 0; }
friend
auto operator>=( const Derived& a, const Derived& b )
-> bool
{ return compare( a, b ) >= 0; }
friend
auto operator>( const Derived& a, const Derived& b )
-> bool
{ return compare( a, b ) > 0; }
};
template< class Type >
struct Index_and_item
{
Index index;
Reference<Type> item;
};
template< class Iterator >
class Enumerator
: public Rel_ops_from_compare< Enumerator< Iterator > >
{
private:
Iterator it_;
Index index_;
public:
using Referent = typename remove_reference<
decltype( *declval<Iterator>() )
>::type;
friend
auto compare( const Enumerator& a, const Enumerator& b )
-> Index
{ return a.index_ - b.index_; }
auto operator->() const
-> Index_and_item< Referent >
{ return Index_and_item< Referent >{ index_, ref( *it_ )}; }
auto operator*() const
-> Index_and_item< Referent >
{ return Index_and_item< Referent >{ index_, ref( *it_ )}; }
Enumerator( const Iterator& it, const Index index )
: it_( it ), index_( index )
{}
auto operator++()
-> Enumerator&
{ ++it_; ++index_; return *this; }
auto operator++( int )
-> Enumerator
{
const Enumerator result = *this;
++*this;
return result;
}
auto operator--()
-> Enumerator&
{ --it_; --index_; return *this; }
auto operator--( int )
-> Enumerator
{
const Enumerator result = *this;
--*this;
return result;
}
};
template< class Collection >
struct Itertype_for_ { using T = typename Collection::iterator; };
template< class Collection >
struct Itertype_for_<const Collection> { using T = typename Collection::const_iterator; };
template< class Type, Size n >
struct Itertype_for_< Type[n] > { using T = Type*; };
template< class Type, Size n >
struct Itertype_for_< const Type[n] > { using T = const Type*; };
template< class Collection >
using Itertype_for = typename Itertype_for_< typename remove_reference< Collection >::type >::T;
template< class Collection >
class Enumerated
{
private:
Collection& c_;
public:
using Iter = Itertype_for< Collection >;
using Eter = Enumerator<Iter>;
auto begin() -> Eter { return Eter( std::begin( c_ ), 0 ); }
auto end() -> Eter { return Eter( std::end( c_ ), std::end( c_ ) - std::begin( c_ ) ); }
//auto cbegin() const -> decltype( c_.cbegin() ) { return c_.cbegin(); }
//auto cend() const -> decltype( c_.cend() ) { return c_.cend(); }
Enumerated( Collection& c )
: c_( c )
{}
};
template< class Collection >
auto enumerated( Collection& c )
-> Enumerated< Collection >
{ return Enumerated<Collection>( c ); }
} // namespace cppx
#include <iostream>
#include <vector>
using namespace std;
auto main() -> int
{
using cppx::enumerated;
cout << "Vector:" << endl;
vector<int> v = {100, 101, 102};
for( const auto e : enumerated( v ) )
{
cout << " " << e.item << " at " << e.index << endl;
}
cout << "Array:" << endl;
int a[] = {100, 101, 102};
for( const auto e : enumerated( a ) )
{
cout << " " << e.item << " at " << e.index << endl;
}
}
关于c++ - 在基于 lambda 的 foreach 循环中模拟 `continue;` , `break;`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28897974/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
假设我在Store的模型中有这个非常简单的方法:defgeocode_addressloc=Store.geocode(address)self.lat=loc.latself.lng=loc.lngend如果我想编写一些不受地理编码服务影响的测试脚本,这些脚本可能已关闭、有限制或取决于我的互联网连接,我该如何模拟地理编码服务?如果我可以将地理编码对象传递到该方法中,那将很容易,但我不知道在这种情况下该怎么做。谢谢!特里斯坦 最佳答案 使用内置模拟和stub的rspecs,你可以做这样的事情:setupdo@subject=MyCl
在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定
我有一个gem,它有一个根据Rails.env的不同行为的方法:defself.envifdefined?(Rails)Rails.envelsif...现在我想编写一个规范来测试这个代码路径。目前我是这样做的:Kernel.const_set(:Rails,nil)Rails.should_receive(:env).and_return('production')...没关系,只是感觉很丑。另一种方法是在spec_helper中声明:moduleRails;end而且效果也很好。但也许有更好的方法?理想情况下,这应该有效:rails=double('Rails')rails.sho