c – 正确使用通用参考

前端之家收集整理的这篇文章主要介绍了c – 正确使用通用参考前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在c 11之前,我曾经写过这样的代码
// Small functions
void doThingsWithA(const A& a)
{
    // do stuff
}

void doThingsWithB(const B& b)
{
    // do stuff
}

void doThingsWithC(const C& c)
{
    // do stuff
}

// Big function
void doThingsWithABC(const A& a,const B& b,const C& c)
{
    // do stuff
    doThingsWithA(a);
    doThingsWithB(b);
    doThingsWithC(c);
    // do stuff
}

但是现在,使用移动语义,允许我的函数将rvalue引用作为参数并添加这些重载可能会变得有趣(至少在某些情况下):

void doThingsWithA(A&& a);
void doThingsWithB(B&& b);
void doThingsWithC(C&& c);

从我收集的内容来看,如果我想在我的大函数调用那些重载,我需要使用完美的转发,这可能看起来像这样(它的可读性稍差,但我想它可以用模板类型的良好命名约定):

template<typename TplA,typename TplB,typename TplC>
void doThingsWithABC(TplA&& a,TplB&& b,TplC&& c)
{
    // do stuff
    doThingsWithA(std::forward<TplA>(a));
    doThingsWithB(std::forward<TplB>(b));
    doThingsWithC(std::forward<TplC>(c));
    // do stuff
}

我的问题是:这是不是意味着如果我的小函数有其他重载,那么可以调用具有不适合的类型参数的大函数

我认为这可能有助于防止这种情况:

template<typename TplA,typename TplC,class = typename std::enable_if<std::is_same<A,std::decay<TplA>::type>::value>::type,class = typename std::enable_if<std::is_same<B,std::decay<TplB>::type>::value>::type,class = typename std::enable_if<std::is_same<C,std::decay<TplC>::type>::value>::type>
    doThingsWithABC(TplA&& a,TplC&& c)
{
    // do stuff
    doThingsWithA(std::forward<TplA>(a));
    doThingsWithB(std::forward<TplB>(b));
    doThingsWithC(std::forward<TplC>(c));
    // do stuff
}

虽然我不确定它是否不是太严格,因为我不知道如果我试图用可隐式转换为A,B或C的类型调用函数它的行为如何……

但是……即使假设这个有效,我真的没有其他选择吗? (我的意思是……眼睛不容易)

解决方法

完美转发主要是因为您不知道如何使用数据,因为您正在编写“用户提供的”数据的通用包装.

在上面描述的一个简单的程序系统中,你做的三件事就是具体的任务.

这意味着你会知道他们是否会从拥有可移动的数据源中受益,如果他们必须复制它们是有意义的,并且如果移动是便宜的话.

如果复制有意义,但移动速度更快,移动便宜(常见情况),它们应该按值获取参数,并在存储本地副本时移出它们.

然后,此规则递归地应用于调用3个子函数函数.

如果该功能不能从移动中受益,请使用const&amp ;.

如果副本没有意义,请使用右值引用(不是通用引用)或按值.

如果您考虑完美转发,在能够移动和移动都很好的情况下仍然很昂贵.如上所述,这通常仅在包装由代码库的“用户”设置的函数时发生,因为通常移动实际上非常便宜,或者像复制一样昂贵.您必须处于移动效率的中间或不确定阶段才能完美转发,这是值得的.

完美转发还有其他用途,例如容器变换器,但它们更为深奥.作为一个例子,我的向后范围变异器将完美地将传入范围转发到存储中,以便在C 11样式基于范围的(:)循环中链接多个范围变换器时,使参考寿命扩展正常工作.

非常完美的转发会导致生成代码膨胀,构建缓慢,实现漏洞以及难以理解的代码.

猜你在找的C&C++相关文章