问题 问题与is_copy_constructible


类型特征是否应该能够处理诸如此类的案例 std::vector < std::unique_ptr <int> > 并检测到它不是可复制构造的?

这是一个例子 https://ideone.com/gbcRUa (运行g ++ 4.8.1)

#include <type_traits>
#include <vector>
#include <iostream>
#include <memory>

int main()
{
    // This prints 1, implying that it's copy constructible, when it's clearly not
    std::cout << std::is_copy_constructible< std::vector<std::unique_ptr<int> > >::value << std::endl; 
    return 0;
}

如果这是正确的行为 is_copy_constructible,有没有办法检测复制结构是否形成错误?好吧,除了让它无法编译之外。


2029
2017-08-23 13:29


起源

可悲的是,是的,这是允许的行为:(。我继续讨论这个问题,为什么我们需要使用SFINAE来防止它,这里: flamingdangerzone.com/cxx11/2013/02/11/... - R. Martinho Fernandes
@ R.MartinhoFernandes:Bleh,我担心你会这么说。我还没找到 is_constructible 之前的问题,但它是相同的答案,因为 is_copy_constructible 是指 is_constructible。 - Dave S
是的,这很烦人。您的问题促使我将问题带到标准提案邮件列表: groups.google.com/a/isocpp.org/d/msg/std-proposals/pgWYGIvV2Tw/...。我应该在2月份这样做,因为C ++ 14提案的截止日期是8月30日。 - R. Martinho Fernandes
@ R.MartinhoFernandes:呃,我想我们可以解决这个问题 decltype 并明确检查但是 显然不是,这也是你所知道的缺陷吗? - Matthieu M.
@MatthieuM。是的,这基本上是同一个问题: decltype 也不会超越眼前的情境。没有任何方法可以解决这个问题 vector :( - R. Martinho Fernandes


答案:


这是因为设计中存在缺陷 std::vectorstd::vector 定义复制构造即使它将无法编译,并依赖于用户 std::vector 如果编译失败,则不调用该方法。

替代设计将是SFINAE阻止方法的调用,如果包含的类型 vector 没有复制构造函数。然而, std::vector 是在现代SFINAE技术发展之前设计的。

它可能会被复制到C ++的新迭代中,因为会有很少的代码会破坏。人们不能说没有代码会破坏,因为你可以拥有依赖于这个事实的代码 std::is_copy_constructible< std::vector< no_copy_type > > 是 std::true_type,或等效的表达式,但这是一个非常奇怪的依赖。

最重要的是 std::vector 比SFINAE技术更早可以解决这个问题,使用SFINAE这样做是非常混乱的(因为SFINAE是一种混乱的技术)。为C ++ 1y提出的新概念 - lite可能会使它更清晰,并且更容易被包含在语言的新迭代中。

当我有一个容器需要知道所包含的对象是否可以被安全地复制,比较和排序时,我的工作是专门的 std::vector 在自定义traits类上,并回退到包含类型上的自定义traits类的值。这是一个拼凑的解决方案,非常具有侵入性。

template<template<typename>class test, typename T>
struct smart_test : test<T> {};
template<template<typename>class test, typename T, typename A>
struct smart_test<test, std::vector<T,A>> : test<T> {}

这给了我们:

template<typename T>
using smart_is_copy_constructible = smart_test< std::is_copy_constructible, T >;

和类似的 < 和 ==。当我遇到更多的容器类型时,我可以添加更多的特殊化,这些容器类型应该真正将它们的属性转发到他们的数据,或者我可以编写一个更高级的SFINAE容器测试和特征并提取底层值类型并将问题发送给测试关于价值类型。

但根据我的经验,我大部分时间都在做这些测试 std::vector


8
2017-08-23 14:26



好吧,你给了我一个有趣的工作。我已经考虑过添加一个专门的模板 is_copy_constructible,但我喜欢你给了我一个我可以在几种类型特征上重复使用的事实。 - Dave S


C ++ 11标准的表49列出了类必须满足的条件 is_copy_constructable<T>::value 是真的,不幸的是并不多:

is_constructable<T, const T&>::value 是 true

因此,如果 std::vector<T> 有一个复制构造函数,它通过了测试。


3
2017-08-23 13:50