c++ - 通过检查复制/移动省略

标签 c++ c++17 copy-elision noncopyable

考虑this 。有一个不可复制、不可移动的类,并且为其定义了一些谓词:

struct AA
{
    AA(AA const&  otehr) = delete;
    AA(AA      && otehr) = delete;
    AA& operator = (AA const&  otehr) = delete;
    AA& operator = (AA      && otehr) = delete;

    AA(int something) { }

    bool good() const { return false; }
};

因为有保证copy/move-elision在 C++17 中我们可以有:

auto getA() { return AA(10); }

问题是:如何定义 getGoodA,在返回 good 时转发 getA,否则抛出异常?这可能吗?

auto getGoodA()
{
    auto got = getA();
    if (got.good()) return got; // FAILS! Move is needed.
    throw std::runtime_error("BAD");
}

最佳答案

如果我们在 C++20 中进行契约检查,您就可以编写如下内容:

auto getGoodA(int i) [[post aa: aa.good()]] {
    return getA(i);
}

(至少我这么认为 - 我并不完全清楚 aa 返回伪变量的类型;它需要是对返回位置中返回对象的引用。 )不幸的是契约(Contract)是 removed from C++20所以我们还需要一段时间才能写这篇文章。

假设您无法修改 getA,目前唯一的方法是从 getGoodA 返回一个包装类。显而易见的解决方案是unique_ptr,但我们实际上不需要执行堆分配;延迟构造包装器将 do just as well :

#include <cstddef>
#include <new>
struct BB {
    alignas(AA) std::byte buf[sizeof(AA)];
    template<class F, class G> BB(F f, G g) { g(*new (buf) AA{f()}); }
    BB(BB&&) = delete;
    ~BB() { reinterpret_cast<AA&>(buf).~AA(); }
    operator AA&() { return reinterpret_cast<AA&>(buf); }
    operator AA const&() const { return reinterpret_cast<AA const&>(buf); }
};
auto getGoodA(int i) {
    return BB{
        [&] { return getA(i); },
        [&](AA& aa) { if (!aa.good()) throw (struct bad**){}; }};
}

这里我给了 BB 一个引用风格的接口(interface),允许你写 AA& aa = getGoodA(i),但你同样可以给它一个指针 -样式接口(interface)(operator*operator->),甚至复制 AA 的接口(interface)。

关于c++ - 通过检查复制/移动省略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62334793/

相关文章:

c++ - 如何在编译时对模板列表进行 "iterate"?

c++ - 保证复制省略和 Nonmoveable{Nonmoveable{}}

c++ - 如何在 Delphi 中使用由 dll 导出的 C++ 类

c++ - clang/gcc 类特化不一致

c++ - 如何提示操作系统哪些内存块不应交换到磁盘?

c++ - experimental::basic_string_view<> 是否适用于右值?

c++ - 为什么我不能推断静态成员函数是否存在

c++ - 在 C++ 复制省略期间如何管理内存?

C++17 复制省略和对象销毁

c++ - 编写应用程序以在没有托管代码的情况下与 SQL 2008 交互