首页 > 解决方案 > 通用“sqr”函数

问题描述

我试图弄清楚如何为 sqr 操作编写“完全通用的函数”(它实际上可以是乘法、除法、加法,并不重要)。

考虑以下代码

#include <iostream>

struct A
{
    int val = 2;

    A() = default;
    A(const A&) = delete; // To make sure we do not copy anything
    A(A&& a) = delete; // To make sure we do not move anything
    auto operator=(auto) = delete; // To make sure we do not assign anything
    // This is important part, we do not want to create a new object on each multiplication.
    // We want just to update the old one.
    A& operator*(const A& a) 
    {
        val *= a.val;
        return *this;
    }
};

// Just for easy printing (you can ignore it).
std::ostream &operator<<(std::ostream &os, const A& a) { 
    return os << a.val;
}

// Here auto&& represents forwarding reference and should automatically understand whether input r or l value.
auto&& sqr(auto&& val)
{
    return val * val;
}

int main()
{
    A a;
    std::cout << sqr(a) << "\n"; // OK
    std::cout << sqr(A()) << "\n"; // OK

    std::cout << sqr(1) << "\n"; // Wrong, ref to local returned
    int i = 2;
    std::cout << sqr(i) << "\n"; // Wrong, ref to local returned
}

sqr这里的函数是一种通用的东西,它应该处理所有可能的情况(r-values,l-values)并且对于 objecta它实际上是这样做的,但不是对于i. 我不明白为什么它试图返回参考而不是复制。有人可以说明情况吗?有什么方法可以轻松完成这项任务(理想情况下使用一个模板函数)?如有必要,我可以使用 c++ 20 标准。

标签: c++c++14c++17c++20

解决方案


auto&& sqr(auto&& val)
{
    return val * val;
}

sqr上面总是返回一个引用。但是返回对本地的引用总是错误的。让返回类型通过使用来推断为非引用auto

auto sqr(auto&& x) // return type is non-reference or trailing
noexcept(noexcept(x*x)) // propagate noexcept
-> decltype(x*x) // enable SFINAE
{ return x * x; }

推荐阅读