【问题标题】:Can I get an istream to emplace rather than assign?我可以让 istream 安顿而不是分配吗?
【发布时间】:2025-11-17 22:10:02
【问题描述】:

istream operator>> 需要对现有对象的引用。这意味着他们所做的是分配而不是就地构建,对吧?

好吧,我怎样才能跳过初始构造?也许编译器可以优化它,但我可能仍然需要提供我宁愿不需要的参数。这完全可以用 istream 完成吗?

...我希望能够拥有,比如说,

template <typename T> void emplace_from(std::istream stream, T* place);

适用于 stream &gt;&gt; my_t_variable 适用的所有类型的 T。虽然,不可否认,这个函数声明看起来有点难看。

【问题讨论】:

  • 不适用于标准设施 AFAIK。您能否举一个您希望实现的语法示例?
  • 标准emplace 调用构造函数。您将构造函数参数传递给它,然后它将它们转发给构造函数。您提议的emplace 无法构造任何东西,因为它不知道如何从流中提取构造函数参数。它不知道要使用 哪个 构造函数!

标签: c++ operator-keyword tokenize istream emplace


【解决方案1】:

使用提取运算符 (std::istream&amp; operator&gt;&gt;(std::istream&amp;, T&amp;)) 无法做到这一点。

但是一般来说std::istream,当然可以。简单地说,实现一个函数T extract(std::istream&amp;) 或类似的。它的实现几乎与提取运算符相同:读取字符流,使用输入初始化新对象,返回对象。然后您可以直接拨打:T t = extract(std::cin)

【讨论】:

  • "simply"...如果我实现了,我根本不需要 istream... :-(
  • @einpoklum 我不太关注你。为什么你根本不需要 istream?
  • 使用 istreams 让我可以将字符串转换为任何类型(为此有人费心实现 operator>>)。没有它们,我不仅需要为我知道的类型实现转换,还需要为我的模板化代码将来使用的任何类型实现转换。
  • @einpoklum 和类似地,istreams 允许您将字符串转换为有人费心实现extract 的任何类型。
  • 是的,问题是人们知道他们应该实现提取,但不知道他们应该实现我的梦想操作。
【解决方案2】:
#include <experimental/optional>

namespace exp = std::experimental;

template<class T, class charT>
exp::optional<T> extract(std::basic_istream<charT>& is) {
    auto it = std::istream_iterator<T, charT>(is);
    if (it != decltype(it)()) {
        return *it;
    }
    return exp::optional<T>{};
}

int main()
{
    int i = *extract<int>(std::cin);
    std::cout << i;
}

【讨论】:

  • 请注意,这要求T 是默认可构造的,因此在but I may still be required to provide parameters I would rather not need to 的情况下它无济于事,我认为这意味着T 实际上不是默认可构造的。
  • @user2079303 那么应该抛出异常或返回nullptr。