gpt4 book ai didi

c++ - 如果底层类型不可复制构造,则为容器生成 is_copy_constructible 的正确方法会产生 false

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:27:17 26 4
gpt4 key购买 nike

这是 std::unordered_map<T,std::unique_ptr<U>> copyable? GCC bug? 的后续行动

假设我们创建了一个模板类 Container:

template<class T>
class Container {
T t;
public:
Container() = default;
Container(const Container& other) : t(other.t) {}
};

不幸的是,is_copy_constructible 因为它产生 true 即使 T 不是可复制构造的:

static_assert(!std::is_copy_constructible<Container<std::unique_ptr<int>>>::value, "Copyable");

由于上述问题的答案中描述的原因,此断言失败,同样是 here is another answer on this topic .

看起来这可以通过像这样制作复制构造器模板来解决:

template<class T>
class Container {
T t;
public:
Container() = default;

template<typename U = void>
Container(const Container& other) : t(other.t) {}
};

这在 GCC 和 clang 中都有效(static_assert 不再失败)。

Ideone Demo

问题:

  1. 从标准的角度来看,这是使 is_copy_constructible 工作的正确方法吗?如果是,添加模板如何影响变量初始化的直接上下文的有效性 (§20.9.4.3/6)?

  2. (可选)是否有更正确或更直观的方法来做到这一点?

注意:声明复制构造函数default 也可以实现这个目标,但并非总是可行。

更新:现在我发现我的解决方案无效,因为复制构造函数不能是模板。这仍然为问题 2 留有余地。

更新 2: 我稍微更改了 ecatmur's answer 中的代码将丑陋从 Container 本身中移除并使其可重用:

struct unused;  // forward declaration only
template<class Container>
using const_ref_if_copy_constructible = typename std::conditional<
std::is_copy_constructible<typename Container::value_type>::value,
Container const&,
unused>::type;

template<typename T>
class Container {
T t;
public:
typedef T value_type;
Container() = default;

Container(const_ref_if_copy_constructible<Container> other) : t(other.t) {}
Container(Container&& other) : t(std::move(other.t)) {}
};

(Demo)

但我对此还是不太满意。对我来说,这看起来像是 C++ 标准中的一个缺陷,因为这些东西不能开箱即用。

最佳答案

那不是按照你的想法去做;模板构造函数永远不会被认为是复制构造函数,因此通过添加 template<typename U = void>到复制构造函数,你正在诱导编译器创建它自己的默认复制构造函数。

一种可能性(除非为不可复制构造的类型提供单独的类模板)是通过将其参数替换为与重载解析无关的参数来禁用复制构造函数:

struct unused;  // forward declaration only

template<typename T>
class Container {
T t;
public:
Container() = default;

Container(
typename std::conditional<
std::is_copy_constructible<T>::value,
Container const&,
unused>::type other)
: t(other.t) {}

Container(Container&& other) : t(std::move(other.t)) {}
};

关于c++ - 如果底层类型不可复制构造,则为容器生成 is_copy_constructible 的正确方法会产生 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25809528/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com