C++ 如何在C++;11?
我正在寻找的代码如下所示C++ 如何在C++;11?,c++,c++11,visual-c++,c++17,C++,C++11,Visual C++,C++17,我正在寻找的代码如下所示 bool Func1(int Arg1, C++11LambdaFunc Arg2){ if(Arg1 > 0){ return Arg2(Arg1); } } 稍后我将使用此代码 Func1(12, [](int D) -> bool { ... } ); 第一个解决方案: 您可以将Func1()函数设置为函数模板: 同样,这将允许您按所需方式调用Func1(): int main() { Func1(12, [
bool Func1(int Arg1, C++11LambdaFunc Arg2){
if(Arg1 > 0){
return Arg2(Arg1);
}
}
稍后我将使用此代码
Func1(12, [](int D) -> bool { ... } );
第一个解决方案: 您可以将
Func1()
函数设置为函数模板:
同样,这将允许您按所需方式调用Func1()
:
int main()
{
Func1(12, [](int D) -> bool { return D < 0; } );
}
int main()
{
Func1(12, [](int D) -> bool { return D < 0; } );
}
intmain()
{
Func1(12,[](int D)->bool{return D<0;});
}
基本版本,用于头文件:
template<typename Lambda>
bool Func1(int Arg1, Lambda Arg2){ // or Lambda&&, which is usually better
if(Arg1 > 0){
return Arg2(Arg1);
} else {
return false; // remember, all control paths must return a value
}
}
通过从std::function
中删除所有权语义,只需键入擦除调用,这样就不需要从std::function
中进行任何分配
第一个示例的一个奇特版本,它还可以更好地处理一些角点情况:(还必须在头文件中实现,或者在使用的同一翻译单元中实现)
模板
布尔函数1(整数Arg1、Lambda和Arg2){
如果(Arg1>0){
返回标准::转发(Arg2)(Arg1);
}否则{
return false;//记住,所有控制路径都必须返回一个值
}
}
它使用了一种称为“完美转发”的技术。对于某些函子,这会生成与#1稍有不同的行为(通常是更正确的行为)
大部分改进来自于在参数列表中使用&
:这意味着传入了对函子的引用(而不是副本),节省了一些成本,并允许传入常量
或非常量
函子
>代码> STD::OpDebug(…)>代码>更改只会导致行为改变,如果某人使用了一种新的C++特性,允许方法(包括<代码>操作程序)>代码>重写<代码>这个//Cux>指针的rVals/LValk状态。从理论上讲,这可能是有用的,但是我看到的基于
this
的右值状态的实际覆盖的函子数量是0
。当我在编写严肃的库代码(tm)时,我会遇到这种麻烦,但很少有其他的麻烦
还有一个可能要考虑的事情。假设您想要获取一个返回bool
的函数,或者一个返回void
的函数,如果该函数返回void
,您想要将其视为返回true
。例如,您使用的函数是在对某个集合进行迭代时调用的,并且您希望有选择地支持早期停止。当函数想要提前停止时,返回false
,否则返回true
或void
或者,在更一般的情况下,如果一个函数有多个重写,其中一个重写接受一个函数,而其他重写在同一位置接受其他类型的重写
这是可能的,这是我在这里要讨论的(使用智能适配器或通过SFINAE技术)。但是,您最好只创建两个不同的命名函数,因为所需的技术太重了
1从技术上讲,
std::function
可以使用magic fairy dust来完成它所做的事情,因为它的行为是由标准描述的,而不是它的实现。我正在描述一个简单的实现,它近似于我与之交互的std::function
实现的行为。对于那些品味更传统的人,请注意,非捕获lambda可以转换为函数指针。因此,您可以将上述函数编写为:
bool Func1(int Arg1, bool (*Arg2)(int)) { ... }
对于传统功能和lambdas,它都能正常工作。+1:4秒太慢了。从技术上讲,您应该使用std::forward(Arg2)(Arg1),但这几乎不值得费心。@Yakk:嗯,我想在调用lambda或函数时这不会有什么区别,对吗?毕竟你没有转发任何东西。如果函子使用了对
this
(作为函数限定符,我的意思是操作符()(…)&&
)的引用,那么它可能与函子有所不同-但是。。。呵呵,不值得打扰IMO:)理论上,无论是[myvec](intx){myvec.push_back(x);return myvec;}
还是手动等效工具都可以意识到它是在右值环境中评估的,并通过移动返回。但是是的,它是非常模糊的。@AndyProwl为什么不向前看呢?即使这对于这个简单的例子来说可能并不重要,但最好使用forward@balki:具体来说,它在这种情况下没有任何区别-如果没有区别,我更喜欢可读性更强的版本。使用模板可以捕获函数指针、函数引用、函数对象、,lambdas(带或不带捕获)、std::函数、std::bind的结果等。如果要传递预先存在的函数或需要与C代码进行互操作,则使用模板也不起作用。没有真正感兴趣的C++纯度方面的论点;这只是我认为被现有答案遗漏的语言的一部分。我得到了C接口参数,但模板将完全绑定到一个预先存在的函数。如果你的对象可以像函数一样被调用,那么模板就可以工作了。我相信你也可以像“const std::function&func”一样传递函数。这比搬家和搬家好/坏吗?我一直认为“const&”意味着只是“传递这个对象”,但&&意味着将对象状态移动到一个新实例(可能称为move copy ctor?)@AlexPetrenko&
通常是一个右值引用,但它也用于名为/(pass this object)的技术中,T&
可以是右值引用或左值引用(在类型推断上下文中——从技术上讲,在任何地方,但很少以这种方式在类型推断之外使用)。
template<typename Lambda>
bool Func1(int Arg1, Lambda Arg2){ // or Lambda&&, which is usually better
if(Arg1 > 0){
return Arg2(Arg1);
} else {
return false; // remember, all control paths must return a value
}
}
bool Func1(int Arg1, std::function<bool(int)> Arg2){
if(Arg1 > 0){
return Arg2(Arg1);
} else {
return false; // remember, all control paths must return a value
}
}
template<class Sig>
struct function_ref;
template<class R, class...Args>
struct function_ref<R(Args...)> {
R operator()(Args...args) const {
return pf(state, std::forward<Args>(args)...);
}
function_ref()=default;
function_ref(function_ref const&)=default;
function_ref& operator=(function_ref const&)=default;
explicit operator bool()const{ return pf!=nullptr; }
// this overload reduces indirection by 1 step
// and allows function_ref<Sig> to resolve overloads
// on an overload set sometimes.
function_ref( R(*f)(Args...) ):
pf([](State const& state, Args&&...args)->R{
return reinterpret_cast<R(*)(Args...)>(state.pfunstate)(std::forward<Args>(args)...);
})
{
state.pfunstate = reinterpret_cast<void(*)()>(f);
}
// this grabs anything callable (that isn't this own type)
// and stores a pointer to it to call later.
template<class F>
requires (
std::is_convertible_v<
std::invoke_result_t< std::remove_reference_t<F>, Args... >, R
>
&& !std::is_same_v< std::decay_t<F>, function_ref >
)
function_ref( F&& f ):
pf([](State const& state, Args&&...args)->R{
return (*(std::remove_reference_t<F>*)state.pstate)(std::forward<Args>(args)...);
})
{
state.pstate = std::addressof(f);
}
private:
union State {
void* pstate = nullptr;
void(*pfunstate)();
};
State state;
R(*pf)(State const&, Args&&...) = nullptr;
};
// a deduction guide permitting function_ref{foo} to work
// if foo is a non-overloaded function name.
template<class R, class...Args>
function_ref( R(*)(Args...) )->function_ref<R(Args...)>;
template<typename Lambda>
bool Func1(int Arg1, Lambda&& Arg2){
if(Arg1 > 0){
return std::forward<Lambda>(Arg2)(Arg1);
} else {
return false; // remember, all control paths must return a value
}
}
bool Func1(int Arg1, bool (*Arg2)(int)) { ... }