【问题标题】:Is the move constructor of ifsteam implicitly deleted?ifsteam的move构造函数是否被隐式删除了?
【发布时间】:2013-01-16 09:57:54
【问题描述】:

我有以下简单的类:

class Source
{
public:
    Source() = default;
    Source(Source const&) = delete;
    Source(Source&&) = default;

    explicit Source(std::string const& fileName)
     : inputStream(fileName), path_(fileName)
    {}

    ~Source() = default;

    auto path() const -> std::string
    {
        return this->path_;
    }

    std::ifstream inputStream;
private:
    std::string path_;
};

auto main(int argc, char* argv[]) -> int
{
    Source source(Source("test.txt"));
    cout << source.path() << "\n";

    return 0;
}

根据cppreference ifstream 有一个move 构造函数,但是当我尝试用MinGW 4.7.2 编译它时,出现以下错误:

..\src\main.cpp:32:46:错误:使用已删除的函数 'cy::Source::Source(cy::Source&&)' 在包含的文件中 ..\src\main.cpp:10:0: source.hpp:28:5: 注意: 'cy::Source::Source(cy::Source&&)' 被隐式删除,因为 默认定义格式错误:source.hpp:28:5: error: use of 删除函数'std::basic_ifstream::basic_ifstream(const std::basic_ifstream&)' c:\mingw\bin../lib/gcc/mingw32/4.7.2/include/c++/fstream:420:11: 注意:'std::basic_ifstream::basic_ifstream(const std::basic_ifstream&)' 被隐式删除,因为默认 定义格式不正确: c:\mingw\bin../lib/gcc/mingw32/4.7.2/include/c++/fstream:420:11: 错误:使用已删除的功能 'std::basic_istream::basic_istream(常量 std::basic_istream&)'

我做错了吗?还是 cppreference 的文档不准确?还是 GCC 4.7.2 有 bug?

【问题讨论】:

  • 移动构造函数没有被删除,复制构造函数被删除。
  • 尝试源码 source(Source("source.txt"));即使您当前的代码是等效的,我相信也需要 operator= 是可访问的。
  • @SethCarnegie,感谢您的提示,但它也不起作用,gcc 仍然说移动构造函数被隐式删除。
  • 只是还没有实现,see here。所有的流都是Missing move and swap operations
  • 使用std::unique_ptr&lt;std::ifstream&gt; 是一种解决方法。

标签: c++ gcc c++11


【解决方案1】:

事实证明,GCC 的标准库实现还没有实现流类的移动和交换操作。有关 gcc 标准库中 C++11 功能的当前状态的详细信息,请参阅here

感谢Jesse Good提供信息和链接。

【讨论】:

  • 我 +1 了答案,因为它有道理,但我在引用的文档中找不到任何引用。
  • @Carneiro,再仔细看看,它就在那里:'27.5 Iostreams 基类、部分、缺少 basic_ios 上的移动和交换操作。'
【解决方案2】:

我意识到这个答案有点晚了,但是为了给一个不可移动的类移动语义,你可以编写一个非常简单的包装类。例如:

#include <memory>



template <typename T>
class swap_wrapper
{
    //! internal buffer to hold object (on heap)
    std::unique_ptr<T> p_obj;
public:
    //! allows any of objects constructors to be called directly
    template <typename... Args>
    explicit swap_wrapper(Args&&... args)
        :   p_obj(
                     new T( std::forward<Args>(args)... )
                     ) {    }

    //! swaps pointer value of T object is unchanged therefore this 
    //! function puts no requirement on base class.

    //! note p_obj is left as a nullptr so dereferencing will cause
    //! undefined behaviour.
    swap_wrapper (swap_wrapper &&other) noexcept
        : p_obj(nullptr)
    {
        swap(other);
    }

    //! swaps pointer like above,
    //! T object is not touched; just the pointer.
    swap_wrapper &operator = (swap_wrapper &&other) noexcept
    {
        swap(other);
        return *this;
    }

    //! uses swap member function of std:unique_ptr
    void swap(swap_wrapper &other) noexcept
    {
        std::swap(p_obj, other.p_obj);
    }

    //! operators to allow access to stream
    T& operator *() { return *p_obj; }
    T const& operator *() const { return *p_obj; }

    T * operator ->() { return p_obj.get(); }
    T const * operator ->() const { return p_obj.get(); }

};


//! overload of default swap (calls member function swap)
template <typename S>
inline void swap(swap_wrapper<S> &one, swap_wrapper<S> &two) noexcept
{ one.swap(two); }

这个包装器可以从函数中返回,作为右值参数传递,等等。

【讨论】:

    猜你喜欢
    • 2022-01-22
    • 2014-01-15
    • 1970-01-01
    • 2012-09-16
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多