【问题标题】:Why doesn't make_optional work for file streams?为什么 make_optional 不适用于文件流?
【发布时间】:2020-07-04 21:16:27
【问题描述】:

我正在尝试 C++17 可选类型,并认为使用它的合适位置是尝试打开文件的函数,也许 返回打开的文件。我写的函数是这样的:

std::optional<std::fstream> openFile(std::string path)
{
    std::fstream file;
    file.open(path);
    if (!file.is_open())
    {
        std::cerr << "couldn't open file" << path << std::endl;
        return {};
    }
    else
    {
        return std::make_optional(file); // results in compilation error
    }
}

但是当我尝试使用 g++ 编译时,-std=c++17 作为参数之一,我收到一大堆模板编译错误消息,开头是:

In file included from read_file.cpp:3:0:
/usr/include/c++/7/optional: In instantiation of ‘constexpr std::optional<typename std::decay<_Tp>::type> std::make_optional(_Tp&&) [with _Tp = std::basic_fstream<char>&; typename std::decay<_Tp>::type = std::basic_fstream<char>]’:
read_file.cpp:16:39:   required from here
/usr/include/c++/7/optional:991:62: error: no matching function for call to ‘std::optional<std::basic_fstream<char> >::optional(<brace-enclosed initializer list>)’
     { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }

为什么看起来fstream 不能与std::optional 一起使用?我是否以错误的方式处理这个问题?如果 optional 不支持流类型,那是不是限制了该类型的应用范围?

【问题讨论】:

  • 第 16 行是哪一行?
  • @ecatmur return std::make_optional(file); // results in compilation error 是第 16 行。

标签: c++ templates c++17 optional filestream


【解决方案1】:

当您将流传递给make_optional 时,您的代码将尝试复制流。流不能被复制,因此,您需要移动它,即,

return std::make_optional(std::move(file));

或者干脆

return file;

(根据编译器的年龄,后者可能不起作用。)

【讨论】:

  • 只是return file ^^
  • 确实,我会将它添加到答案中,但它会隐藏实际发生的事情。
  • 我更喜欢隐藏并欣赏“它只是工作”。 ymmv。
  • 我认为长格式用于教育,短格式用于实际代码。
  • 我正在使用 g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0,并且仅仅返回文件会导致编译错误,因为它显然没有将流隐式转换为可选.但是,将流显式移动到 make_optional 确实 工作!谢谢。
【解决方案2】:

std::make_optional 调用可选构造函数,形式为

template < class U = value_type >
constexpr optional( U&& value );

并且构造函数的行为就像在做

T optional_data = std::forward<U>(value)

因为你传递了一个左值,所以它将进行复制。流不可复制,因此您会收到错误消息。您必须将流move 输入可选项才能使其正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-17
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-23
    相关资源
    最近更新 更多