如何避免转换运算符调用复制构造函数?

How do I avoid a conversion operator to invoke the copy constructor?

作为 optimization/cleanup 通过的一部分,我正在尝试了解如何减少临时副本。在执行此操作时,我注意到转换运算符调用了我的 class 的复制构造函数,否则可以避免这种情况。

struct CSetViewer
{
    int s;
    CSetViewer(int size) : s(size) {}
    CSetViewer(const CSetViewer &) = delete;
    CSetViewer &operator=(const CSetViewer &) = delete;
    CSetViewer(CSetViewer &&) = delete;
    CSetViewer &operator=(CSetViewer &&) = delete;

};

struct CSet
{
    operator CSetViewer() { return {1}; }
    CSetViewer GetSetViewer() { return {1}; }
};

void testSet(const CSetViewer &set) {}

void main()
{
    CSet set;
    testSet(set.GetSetViewer());
    testSet(set); // Error: attempting to reference a deleted function
}

在下面的代码中,第一次调用 testSet 编译正常,但第二次似乎想要调用复制构造函数。

添加:

void testSet(CSetViewer &&set) {}

使代码编译(VS 2017),但我真的不明白为什么我认为 const-reference 版本在这种情况下就足够了。

转换运算符与 GetSetViewer 函数有何不同?我可以在不调用复制或移动构造函数的情况下使上面的代码与转换运算符一起工作吗?

这是a known bug of Microsoft Visual Studio。错误报告已提交 2018-11-12。那里没有消息。