【问题标题】:How to read a value with operator>> but no default constructor to the value?如何使用 operator>> 读取值但没有该值的默认构造函数?
【发布时间】:2010-12-11 02:21:29
【问题描述】:
template <class T>
T Read () {
  T t;
  cin >> t;
  if (cin.fail()) {
    // ...
  }
  return t;
}

这个通用代码读取 T 类型的值,并进行了一些额外的错误处理。 它依赖于具有可以解析 T 的 operator>>,并且通过这种方式它可以扩展到新类型。

我没有意识到它依赖于 T 具有默认构造函数。 现在我遇到了这个问题。

我有什么选择?

正确的做法是什么?

【问题讨论】:

    标签: c++ stream default-constructor


    【解决方案1】:

    来自输入流的流式传输始终假定要写入一个完全构造的对象。你无法绕过必须构造一个对象,你所能做的就是允许不同的方式来做到这一点。

    做到这一点的一种方法可能是特征。标准特征会做你正在做的事情:

    template< typename T >
    struct istream_traits
    {
      inline static T read(std::istream& is)
      {
        T obj;
        is >> obj;
      }
    }
    
    template< typename T >
    inline T read(std::istream& is)
    {
      is >> std::ws;
      T obj = istream_traits<T>::read(is);
      is >> std::ws;
      if(!is.eof()) throw "dammit!";
      return obj; 
    }
    

    如果你有一个类型 X 不能默认构造,但可以从 istream 构造,下面的特化就可以了:

    template<>
    struct istream_traits<X>
    {
      inline static X read(std::istream& is)
      {
        return X(is);
      }
    }
    

    【讨论】:

    • 我猜“istream_traits::read(is);”应该是“istream_policy::read(is);”
    • 我可以做一个大规模的专业化,即不是单独针对每种类型,而是像“如果没有默认构造函数尝试 X(istream&) 并且如果失败也尝试命名构造函数:XX::OfStream (istream&); ?
    • 使用Concept Checking + SFINAE,我想这是可能的。
    • @Łukasz:我为愚蠢的错误道歉。 (已经过了凌晨 2 点,以防这算作借口。)正如 Matthieu 已经指出的那样,有模板技术可以做这些事情。作为另一个想法,boost (boost.org) 有一个全面的类型特征库,它可能有类似is_default_constructible 的东西。 (我没用过,所以我不知道。)关于“其他一切”的专攻:你反其道而行之,专攻除“其他一切”之外的一切。阅读 Andrei Alexandrescu 的这篇经典文章:erdani.com/publications/traits.html
    • @sbi,谢谢。我可以使用 boost 来检查一个类型是否具有静态命名构造函数 OfStream?
    猜你喜欢
    • 1970-01-01
    • 2012-01-10
    • 2021-12-16
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2016-07-18
    • 1970-01-01
    相关资源
    最近更新 更多