代码之家  ›  专栏  ›  技术社区  ›  bugybunny

折叠表达式的值类别总是prvalue吗?

  •  5
  • bugybunny  · 技术社区  · 7 年前

    折叠表达式总是prvalue吗?这是正确的吗?

    template<typename... Args>
    auto sum(Args... args) {
        auto fold = (... +  args);
        return fold;
    }
    
    int main() {
        sum(10, 2, 2);
    }
    

    (... + args) 在上述示例中。

    4 回复  |  直到 7 年前
        1
  •  7
  •   Brian Bi    7 年前

    折叠表达式的语义与简单写出运算符的N-1应用程序(其中N是包中的元素数)相同。例如 sum(10, 2, 2) (10 + 2) + 2 . 看见 [temp.variadic]/9

    + 自内置 + args 然后 (... + args) 这与简单地用假设名称提及一个元素是一样的,因此结果将是左值。当然,您也可以使用其他(可能重载)运算符进行折叠,这可能会生成GLValue。

        2
  •  4
  •   StoryTeller - Unslander Monica    7 年前

    不一定是这样。这完全取决于操作员。如果你要使用 +=

    template<typename... Args>
    auto sum(Args... args) {
        auto fold = (... +=  args) = 3;
        return fold;
    }
    

    由于 += 是一个指定左手操作数的左值(为了简单起见,我不考虑疯狂的重载),折叠表达式也最终生成左值。所以最后的作业是完全有效的,虽然很臭。

        3
  •  2
  •   Passer By    7 年前

    折叠表达式不影响表达式的值类别,它实际上只是编译器为您扩展参数包

    template<typename... Args>
    void foo(Args&... args)
    {
        (args, ...) = 42;
    }
    
    void bar()
    {
        int x, y, z;
        foo(x, y, z);
    }
    

    有效,因为 (args, ...) int&

        4
  •  2
  •   AndyG    7 年前

    我真的很喜欢 @Brian @Passer By

    让我们首先修改求和函数以使用 decltype(auto)

    template<typename... Args>
    decltype(auto) sum(Args&&... args) {
        decltype(auto) fold = (... +  std::forward<Args>(args));
        return fold;
    }
    

    功能仍然相同,只是现在 sum 将返回 确切地 类型: fold 是,并且 将承担 准确的 总和的类型。

    一元左折

    ((E) 1. 2. )op…)op EN公司

    Args 可以被视为长度数组 N :

    ((Args[0] + Args[1]) + ...) + Args[N-1]
    

    Args[0] + Args[1] + ... + Args[N-1]
    

    所以,现在我们已经从整个事物中去掉了一些神秘主义,不需要太多的时间就可以看到,表达式的类型实际上只是将表达式两边遇到的任何类型相加的结果的类型 + 操作人员

    Foo 这有一些奇怪的加法语义:

    const std::string global = "Global string";
    
    struct Foo{
        Foo(int){}
    };
    
    const std::string& operator +(const Foo&, const Foo&){
        return global;
    }
    const std::string& operator +(const std::string& _str, const Foo&){
        return _str;
    }
    

    总和 对于 ,我将收到 const std::string& 作为回报,这绝对不是prvalue:

    int main() {
        std::cout << sum(Foo{10}, Foo{2}, Foo{2}) << std::endl;
    }
    

    打印

    全局字符串