通用“sqr”函数

Dmi*_*try 0 c++ c++14 c++17 c++20

我试图弄清楚如何为 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
}
Run Code Online (Sandbox Code Playgroud)

sqr function here is meant to be sort of generic stuff, it should handle all possible situations (r-values, l-values) and for object a it's actually does, but not for i. I can't get why it's trying to return reference instead of copy. Could anyone please shed some light on the situation? Is there any way I can accomplish this task easily (with one template function ideally)? I can use c++ 20 standard if necessary.

Ded*_*tor 5

auto&& sqr(auto&& val)
{
    return val * val;
}
Run Code Online (Sandbox Code Playgroud)

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

constexpr // May be constexpr for some types
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; }
Run Code Online (Sandbox Code Playgroud)