1

这开始是一个问题:“为什么不能显式实例化 std::unique_ptr 的 std::vector?” 如:

template class std::vector<std::unique_ptr<int>>;

尽管以下显式实例化和变量很好:

template class std::vector<int>;
template class std::unique_ptr<int>;

int main() {
    std::vector<int> ints;
    std::vector<std::unique_ptr<int>> pointers;
}

但问题变成了:“有什么替代方案?”

我将发布我的演练来回答这两个问题,因为我没有找到一个感觉足够相似的问题。我也在寻找替代品,如果有的话。

4

1 回答 1

1

为什么不可能?

这是不可能的:

template class std::vector<std::unique_ptr<int>>; // (1)

尽管编译器对这样的变量完全没有问题:

std::vector<std::unique_ptr<int>> vec; // (2)

据我所知,(2)是可能的,因为使用复制分配/构造函数的方法永远不会在向量中隐式实例化;
并且 (1) 是不可能的,因为向量试图实例化试图在 unique_ptr 上复制的方法。

例如,第一种不为 gcc 7.2.1 c++17 编译的方法是vector::push_back(const T&);

因为 T = unique_ptr,而 unique_ptr 显然不支持复制操作。

有哪些替代方案?

shared_ptr 而不是 unique_ptr 有效,因为它支持复制分配,同时看起来也很干净。但正如我听说的那样,它有一些开销,并且无意共享资源所有权。

我还想象编写一个包装器,它定义了“复制”操作,它实际上会继续复制甚至抛出,例如:

template<typename T>
struct UniquePtrWithCopy {
    /*mutable if move is used*/ std::unique_ptr<T> mPtr;

    UniquePtrWithCopy() = default;

    explicit UniquePtrWithCopy(std::unique_ptr<T>&& other)
            : mPtr{std::move(other)} {
    }

    UniquePtrWithCopy(const UniquePtrWithCopy& other) {
        mPtr = std::move(other.mPtr); // needed for operations, like resize
        // or
        throw std::runtime_error{"This is not intended"};
    }

    UniquePtrWithCopy& operator =(const UniquePtrWithCopy& other) {
        if(this != &other) {
            mPtr = std::move(other.mPtr);
        }
        return *this;
        // or
        throw std::runtime_error{"This is not intended"};
    }
};

然后这是可能的:

template class std::vector<UniquePtrWithMovingCopy<int>>;

所以我想,虽然我试图找到答案,但毕竟我自己已经找到了,但我很高兴听到其他一些方法或修复。

但是,如果编译器做了某种 sfinae 技巧并且只部分实例化任何可能的东西,那就太好了,但这可能有它自己的一些问题。

于 2017-12-29T15:52:43.637 回答