简体   繁体   English

如何使用命名变量为const rvalue引用参数定义默认值?

[英]How to define default for a const rvalue reference parameter using a named variable?

I have a complex class type and I want to define a default constant instance that can be copied an used as a parameter to a function. 我有一个复杂的类类型,我想定义一个默认的常量实例,该实例可以复制用作函数的参数。 I also want to use that instance as a default parameter so the function can be called without it. 我也想将该实例用作默认参数,以便在没有该实例的情况下调用该函数。 The function expects a const rvalue reference. 该函数需要一个常量值引用。

In the following code, the disadvantage of function test1 is that the code for the definition of the default value is duplicated. 在以下代码中,函数test1的缺点在于,用于定义默认值的代码是重复的。

Is the function test2 valid? 函数test2有效吗? Will the defaultS be left in unspecified state after the first call? 第一次调用后,defaultS会保持未指定状态吗? In that case, is there a better way to avoid code duplication? 在那种情况下,是否有更好的方法来避免代码重复?

The code prints 2 1 1 as expected when compiled with or without optimization (gcc 4.8). 无论是否进行优化(gcc 4.8)进行编译,该代码都会按预期输出2 1 1。 However, can it be relied on to work with any compiler (that supports c++11)? 但是,可以依靠它与任何支持c ++ 11的编译器一起工作吗?

#include <iostream>
#include <utility>

struct S {
    // Imagine that this is a very complex class.
    int data1, data2, data3;
};

// Duplicated code for defining default parameter and the constexpr.
// This example is trivial, but remember that S is more complex in a real use case.
constexpr S defaultS = {0, 0, 1};
void test1(const S&& arg = S{0, 0, 1}) {
    std::cout << arg.data1 + arg.data2 + arg.data3 << std::endl;
}

// Default values are defined only once when defining defaultS.
// Will defaultS be unspecified after first call?
void test2(const S&& arg = std::move(defaultS)) {
    std::cout << arg.data1 + arg.data2 + arg.data3 << std::endl;
}

int main(int argc, char **argv) {
    // Use case for defaultS.
    // Most values are default but a few are changed.
    auto param = defaultS;
    param.data3 = 2;
    test1(std::move(param));

    test2(); // defaultS is moved from.
    test2(); // defaultS is used again here. Is it unspecified?
             // and will there therefore be undefined behaviour?

    return 0;
}

Since std::move(defaultS) deduces the argument type as S const& and returns a typename std::remove_reference<S const&>::type&& , ie, a S const&& I'd think the code is OK: you won't be able to move from the S const&& as the object is const . 由于std::move(defaultS)将参数类型推导为S const&并返回类型名称typename std::remove_reference<S const&>::type&& ,即S const&&我认为代码是可以的:您不会可以从S const&&移动,因为对象是const

It doesn't make much sense to take a S const&& as argument, I'd think. 我认为以S const&&作为参数没有太大意义。 When you want to take a S&& as argument you would need to create an object, eg using 当您想使用S&&作为参数时,您需要创建一个对象,例如使用

void foo(S&& value = S(defaultS)) { ... }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM