c++ lambda返回类型自动推导的一些需要注意的地方

时间:2020-11-26 19:32:16

一句话,lambda返回类型自动推导走的是auto,而不是decltype,注意。

class ObjectA
{
public:
    ObjectA()
    {
        val_ = ++g;
    }

    ObjectA(const ObjectA& other)
    {
        val_ = ++g;
    }

    ~ObjectA()
    {
        val_ = 0;
    }

    ObjectA& operator=(const ObjectA& other)
    {
        if (this != &other)
        {
            val_ = ++g;
        }
        return *this;
    }

    int val_;
};

const ObjectA& funcPlaceholder()
{
    return ObjectA();
}

class Test
{
public:
    ObjectA& returnValue()
    {
        return val_;
    }

    const ObjectA& returnConstValue() const
    {
        return val_;
    }

    ObjectA val_;
};

void useRetValRef(std::function<ObjectA&()> func)
{
    ObjectA& v = func();
}

void useRetValConstRef(std::function<const ObjectA&()> func)
{
    const ObjectA& v = func();
    const ObjectA& v2 = funcPlaceholder();
}

int main(int argc, wchar_t* argv[])
{
    Test tt;
    // 下面的lambda使用了自动返回类型推导->ObjectA,而不是ObjectA&,所以编译器报错,函数类型不匹配
    // f的类型是ObjectA(),而使用f的要求是ObjectA&()
//     auto f = [&tt](){return tt.returnValue();};
//     useRetValRef(f);
    // 下面这个情况也类似,j是ObjectA类型而不是ObjectA&
    auto j = tt.returnValue();
    j.val_ = 10;
    // 这样i就是ObjectA&了,decltype是编译时推导,不会产生任何运行时代码
    decltype(tt.returnValue()) i = tt.returnValue();
    i.val_ = 10;

    tt.val_.val_ = 20;

    // 下面会引起warning C4172: returning address of local variable or temporary,
    // 因为lambda使用了自动返回类型推导->ObjectA,函数返回值,而不是引用
    // 而使用f2的地方用const&接收了这个值,所以模版展开后出现类似这样的代码
    /*
    const ObjectA& func()
    {
        return ObjectA();
    }
    */
    auto f2 = [&tt]()
    {
        return tt.returnConstValue();
    };
    useRetValConstRef(f2);

    return 0;
}