类型特征是否应该能够处理诸如此类的案例 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
,有没有办法检测复制结构是否形成错误?好吧,除了让它无法编译之外。
这是因为设计中存在缺陷 std::vector
。 std::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
。
C ++ 11标准的表49列出了类必须满足的条件 is_copy_constructable<T>::value
是真的,不幸的是并不多:
is_constructable<T, const T&>::value
是 true
因此,如果 std::vector<T>
有一个复制构造函数,它通过了测试。