简体   繁体   English

C ++:转换运算符重载和引用

[英]C++: Cast operator overloading and references

C++ allows for overloading type casts by creating an operator T() where T is the type we want to cast to. C ++允许通过创建operator T()来重载类型转换,其中T是我们想要转换的类型。

Now, how does this feature play together with references? 现在,此功能如何与引用一起使用? For example: 例如:

struct Y{ int i; };

struct X{
    Y y;

    operator Y() const { return y; }
};

Here, we can cast an X to Y which will simply return the contained Y . 在这里,我们可以将XY ,这将简单地返回包含的Y But what if we want to make a cast to an Y reference. 但是,如果我们想要对Y引用进行转换,该怎么办呢? For example, C++ allows us to do this: 例如,C ++允许我们这样做:

struct X{
    Y y;

    operator Y&(){ return y; }
    operator const Y&() const { return y; }
};

Now, we can cast an X to a Y reference or a const reference (which also works for a const X ). 现在,我们可以将X转换为Y引用或const引用(也适用于const X )。

Is there any difference in the semantics of the first and the second example? 第一个和第二个例子的语义有什么不同吗? What is the best way if I want to allow casting to a reference? 如果我想允许转换为引用,最好的方法是什么?

I could imagine that even if I write operator T() without any & , C++ might allow that the cast returns a result by reference (ie, it might somehow add implicit operator T&() methods when I specify operator T() ). 我可以想象,即使我在没有任何&情况下编写operator T() ,C ++可能允许转换通过引用返回结果(即,当我指定operator T()时,它可能以某种方式添加隐式operator T&()方法。

For example, I want the following code to work: 例如,我想要以下代码工作:

int main(){
    X x;
    Y& y = x; // y now references the y inside x
    y.i = 5;
    std::cout << x.y.i << std::endl; // Should print 5 now
}

What is the most simple way to achieve this? 实现这一目标的最简单方法是什么?

Does declaring a operator T() imply that the cast always returns a T by value? 声明operator T()是否意味着强制转换始终返回T值?

Yes. 是。

The return type of conversion operators is implicitly exactly what they convert to. 返回类型的转换运算符隐式正是它们转换为的内容。

[...] the type of the conversion function is “function taking no parameter returning conversion-type-id”. [...]转换函数的类型是“不返回convert-type-id的参数的函数”。

§12.3.2 [class.conv.fct] §12.3.2[class.conv.fct]

With clang++: 使用clang ++:

#include <iostream>

class   test
{
public:
  test(int n) : nb{n} {}

public:
  operator int() { return nb; }

  private:
    int nb;
};

int     main(void)
{
  test  t{42};

  int x = t;

  int& ref = t;   // error: non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'test'
  int&& rref = t; // compiles fine

  std::cout << x << std::endl;
}

Which suggest that you do return a temporary new value. 这表明你确实返回了一个临时的新值。

The real question to help you choose between your two cases is: do you want to let people modify your internal member (return a reference) and is that member expensive to copy (use a const reference instead of value) ? 帮助您在两种情况之间做出选择的真正问题是: 您是否希望让人们修改您的内部成员(返回引用)并且该成员是否需要复制(使用const引用而不是值)?

Does declaring a operator T() imply that the cast always returns a T by value? 声明operator T()是否意味着强制转换始终返回T值?

It means that the conversion operator will return as specified by T . 这意味着转换运算符将按T指定的方式返回。 Be that a reference, pointer or value. 是一个引用,指针或值。 For example, given some type (as per the OP) Y : 例如,给定某种类型(根据OP) Y

operator Y();
operator Y&();
operator Y*();

Are all (with the cv-qualified variations) valid user defined conversions. 所有(使用cv限定的变体)都是有效的用户定义转换。 To use Y as a reference, you will need to return it as a reference. 要使用Y作为参考,您需要将其作为参考返回。

So, yes, casting to a T that is not a reference means that the return type is a value. 所以,是的,转换为不是引用的T意味着返回类型是一个值。 This is inline with the general casting semantics - a value is returned. 这与一般的强制转换语义一致 - 返回一个值。

Is there any difference in the semantics of the first and the second example? 第一个和第二个例子的语义有什么不同吗?

Yes there are semantic differences. 是的,存在语义差异。 They would be the same semantic deferences as in other methods with reference vs. value return types. 它们与引用与值返回类型的其他方法具有相同的语义差异。 They would be different in the same way as the following two methods are different; 它们的不同之处在于以下两种方法不同;

Y get_y_value();
Y& get_y_ref();

Notes 笔记

Mixing operator Y(); 混合operator Y(); and operator Y&(); operator Y&(); in the same class could lead to ambiguous overloads (at least clang complains about this, but gcc seems happy to mix the two). 在同一个班级可能导致模糊的超载(至少clang抱怨这个,但gcc似乎很乐意混合这两个)。

I'm not going to opinion on which one is better here as the details of your situation are unclear. 由于你的情况细节尚不清楚,我不会就哪一个更好的问题发表意见。 In general though, when implementing a user defined conversion, always consider how casts are typically performed and that rvalues are probably returned more often than not. 通常,在实现用户定义的转换时,始终要考虑通常如何执行转换以及可能更频繁地返回rvalues。 With the advent of C++11, favour them being explicit as well; 随着C ++ 11的出现,也赞成它们也是explicit ; for the same reasons constructors are explicit (or not if specifically required). 出于同样的原因,构造函数是explicit (如果特别需要,则不是)。

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

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