【问题标题】:C++ conversion const pass-by-referenceC++ 转换 const 传递引用
【发布时间】:2011-09-30 15:12:41
【问题描述】:

给定模板传递引用转换/类型转换运算符(不带 const)是可能的:

class TestA
{
    public:

        //Needs to be a const return
        template<typename TemplateItem>
        operator TemplateItem&() const {TemplateItem A; A = 10; return A;}
};

int main()
{
    TestA A;
    {
        int N;
        N = A;
        printf("%d!\n",N);
    }
    {
        float N;
        N = A;
        printf("%f!\n",N);
    }
    return 0;
}

并给出以下代码(带 const):

class TestA
{
    public:

        //Produces error
        template<typename TemplateItem>
        operator const TemplateItem&() const {TemplateItem A; A = 10; return A;}
};

产生这些错误:

错误:无法在分配中将“TestA”转换为“int”
错误:无法在赋值中将“TestA”转换为“float”

问题

如何使转换/类型转换运算符返回模板类型的 const 传递引用?

上下文

在大多数人进来并为“您无法将其转换为任何东西”而感到震惊之前,您需要了解上下文。上面的代码是伪代码——我只对可能的 const 引用返回感兴趣,而不是模板化转换函数的缺陷。但如果你想知道它的用途,那就相对简单了:

TemplateClass -> 转换(转成字节数据) -> 文件
TemplateClass

用户应该知道他们正在输出什么,或者应该是自动化的(即保存/加载状态)。是的,模板有一种通用方法,使用指针将任何类型转换为字节数据。

而且不要给我吹嘘 std 已经在做这种事情了。转换过程是更复杂的类库设置的一部分。

我是一名程序员。相信我。 C++ 信任我,让我犯错。只有这样我才能学习。

【问题讨论】:

  • @Als:你的意思是,像那种转换方法……在课堂上,对吗?
  • 一般建议:您不应返回对临时值的引用。而是返回一个值:operator TheType() const {...},否则,您可能会产生一个悬空引用。
  • @Als 他已经用转换功能做到了。我认为您的意思是“不要使用转换函数来这样做。”
  • @JohannesSchaub-litb:啊,感谢您纠正这个错字。我要删除那个。
  • @SS 第一句话是错的。我建议阅读 C++ 规范。我不知道你的其他陈述是什么意思。

标签: c++ templates operator-overloading conversion-operator


【解决方案1】:

首先,您的转换运算符已经是未定义的行为,因为您返回了对超出范围的局部变量的引用(无论是否为 const)。如果您将转换运算符更改为不会导致 UB 的按值返回,它应该可以正常工作。

编辑:(删除了有关转换运算符的错误信息)。

但是你真的确定你真的希望你的类类型可以转换成任何东西吗?这似乎只会在您将来维护代码并自动转换为意外类型时引起很多麻烦。

另一种可能的实现是创建一个as 模板方法,该方法基本上可以完成您的转换操作员想要做的事情,并将其称为obj.as&lt;int&gt;()

【讨论】:

  • 你的第一句话是绝对正确的。你的答案的其余部分......好吧,转换运算符是 C++ 允许基于结果类型重载的一个地方(请注意,严格来说,结果类型不是基于返回类型的重载——它是运算符名称的一部分)
  • 我认为可以保证临时对象在使用它们的操作(即分配)超出范围之前不会被销毁。如果它适用于传递复制(并且模板类不会处理小的整数和浮点数 - 我们正在谈论像 const char 数组和图形的大类这样的怪物),它应该适用于传递引用,给定在分配完成之前,临时的,无论是通过副本还是参考,都不会超出范围。确定吗?
  • “但你真的确定吗?”...我非常肯定。相信我作为一名程序员,我知道在正常情况下的陷​​阱,但我使用低级二进制数据转换,从内存 IE 文件加载类,因此它可以适用于任何类型 - 但用户应该知道什么存储在文件中(或者预计会为它们自动执行)。但这并不能回答我关于模板 const 参考的问题。
  • @SSight3:这里没有临时的;只是一个在函数返回时超出范围的自动变量。访问返回的引用会给出未定义的行为。您应该改为按值返回并相信您的编译器会忽略副本,或者在 C++11 中确保您的大类型是可移动的。
猜你喜欢
  • 2012-06-14
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多