【问题标题】:Unable to use ternary operator to conditionally assign `istream &`?无法使用三元运算符有条件地分配`istream &`?
【发布时间】:2019-08-01 18:30:32
【问题描述】:

我有一个接受std::istream & 的构造函数,并在分配其中一个成员(std::istream &)之前对其进行检查。例如:

class Stream
{
    public:
    Stream(std::istream &is) : s_ {is.good() ? is : throw std::runtime_error {"Invalid input stream\n"}} 
        {}

    private:
    std::istream &s_;
};

编译器抱怨std::basic_istream(const basic_istream &) 的构造函数被删除(可以理解,因为你不能复制流)。但是,我看不到这里在哪里进行了复制?它必须在三元运算符内,因为

Stream(std::istream &is) : s {is} {}

没有检查工作正常。 std::istream 试图被复制到哪里?我该如何解决这个问题?

【问题讨论】:

  • 编译器无法判断通用类型。
  • 我很确定问题出在throw,而不是三元运算符。
  • @VladfromMoscow 应该是,不过,throw 表达式是 void?: 有专门的措辞来处理它。
  • 添加接受istream&并返回istream&的辅助方法,在里面你可以检查good调用,如果失败抛出异常。 s_{testMethod(is)}.
  • @rafix07 这是否意味着我的构造函数必须捕获该异常并抛出它? (例如)如果调用者想要处理它?

标签: c++ ternary-operator


【解决方案1】:

这个GCC bug 64372

conditional operator 的 cppreference 中,我们了解到如果条件运算符的一个操作数是 throw 表达式,“[t]条件运算符的结果具有另一个表达式的类型和值类别。”因此,您使用条件运算符的结果应该是std::istream&,但GCC thinks it's std::istream


要解决这个 GCC 错误,请使用辅助函数:

class Stream
{
    public:
    Stream(std::istream &is) : s_ {validated_stream(is)} 
        {}

    private:
    std::istream &s_;

    static std::istream &validated_stream(std::istream &is) {
        if (!is.good()) throw std::runtime_error {"Invalid input stream\n"};
        return is;
    }
};

【讨论】:

  • 谢谢。但是这个错误是从 2014 年开始的?为什么还没修好?
  • @DavidTran 我和你一样感到惊讶。我猜编译器开发人员有很多事情要做,而且使用条件运算符这一方面的人并不多。
  • 已知至少 GCC 9.0 可以工作。尽管如此,那还是一段漫长的干燥期。
  • @Deduplicator 它被标记为在 GCC 9.0 中工作,但注意 Jonathan Wakely's comment;它可能没有被修复(事实上,我发布的上帝螺栓链接显示——至少它的这个实例——仍然被破坏:godbolt.org/z/2wEtD1
猜你喜欢
  • 2010-09-20
  • 2017-11-09
  • 2012-07-03
  • 2021-12-08
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多