std :: vector <t>是“用户定义的类型”吗?</t>

时间:2014-05-14 15:39:01

标签: c++ c++11 language-lawyer template-specialization c++14

在17.6.4.2.1 / 1和17.6.4.2.1 / 2中,current draft standard限制被放置在用户注入namespace std的专业化中。

  

C的行为   ++   如果程序向命名空间添加声明或定义,则程序未定义   STD   或者   名称空间中的名称   STD   除非另有规定。程序可以添加模板专业化   任何标准库模板到命名空间   STD   仅当声明取决于用户定义类型时   并且专业化符合原始模板的标准库要求,并未明确说明   禁止的。

我找不到标准中的位置用户定义类型的定义。

我听到的一个选项是,非std::is_fundamental的类型是用户定义的类型,在这种情况下,std::vector<int>将是用户 - 定义类型

另一个答案是用户定义类型是用户定义的类型。由于用户未定义std::vector<int>std::vector<int>不依赖于用户定义的任何类型,std::vector<int>不是用户定义类型

这个影响的一个实际问题是“你可以为std::hash注入std::tuple<Ts...> namespace std的特殊化吗?能够做到这一点有点方便 - 另一种方法是创建另一个我们递归地为std::tuple构建哈希的命名空间(以及std中可能没有hash支持的其他类型),当且仅当我们无法在该命名空间中找到哈希时我们是否会依赖std

但是,如果这是合法的,那么如果标准为hash std::tuple添加了namespace std专门化,那么专门用于它的代码就会被破坏,从而产生一个原因而不是在将来添加此类专业。

虽然我在谈论std::vector<int>作为具体示例,但我想问一下std中定义的类型是否用户定义类型。第二个问题是,即使没有,也许std::tuple<int>在用户使用时会变成用户定义的类型(这会变得很滑:如果std内的某些内容定义了会发生什么std::tuple<int>,您对hashstd::tuple<Ts...>进行了部分专业化。


此问题目前有open defect

4 个答案:

答案 0 :(得分:33)

教授。 Stroustrup非常清楚,任何非内置的类型都是用户定义的。请参阅“使用C ++编程原理和实践”中第9.1节的第二段。

他甚至特别提到“标准库类型”作为用户定义类型的示例。换句话说,用户定义的类型是任何复合类型。

Source

文章明确提到不是每个人似乎都同意,但这是恕我直言,大多是一厢情愿的想法,而不是标准(和Stroustrup教授)实际说的是什么,只有一些人想要读到它。

答案 1 :(得分:16)

当第17条说&#34;用户定义&#34;它意味着&#34;一种未在标准中定义的类型&#34;因此std::vector<int> 是用户定义的,std::string也不是,因此您无法专门化std::vector<int>std::vector<std::string>。另一方面,struct MyClass是用户定义的,因为它不是标准中定义的类型,因此您可以专门化std::vector<MyClass>

这与&#34;用户定义&#34;的含义不同用于第1-16条,这种差异令人困惑和愚蠢。有一个defect report,有一些讨论基本上说是#34;是的,图书馆使用错误的术语,但我们没有更好的一个&#34;。

所以问题的答案是&#34;它取决于&#34;。如果您正在与C ++编译器实现者或核心语言专家交谈,std::vector<int>肯定是用户定义的类型,但如果您正在与标准库实现者交谈,则不是。更确切地说,就17,6.4.2.1 而言,它不是用户定义的

查看它的一种方法是标准库是&#34;用户代码&#34;就核心语言而言。但是标准库对用户&#34;用户有不同的看法。并认为自己是实施的一部分,只有不属于图书馆的部分才是用户定义的#34;。

编辑:我建议更改库子句以使用新术语&#34;程序定义&#34;,这意味着在您的程序中定义的内容(而不是在定义的UDT中)标准,例如std::string)。

答案 2 :(得分:7)

  

由于用户未定义std::vector<int>,并且std::vector<int>不依赖于用户定义的任何类型,std::vector<int>不是用户定义的类型。

逻辑计数器参数是用户执行定义std::vector<int>。您看到std::vector类模板,因此在二进制代码中没有直接表示。

从某种意义上说,它通过类型的实例化获得二进制表示,因此声明std::vector<int>对象的动作就是给模板提供“灵魂”(原谅措辞)。在没有人使用 std::vector<int> 的程序中,此数据类型不存在。

另一方面,遵循相同的论点,std::vector<T> 是用户定义的类型,它甚至不是一个类型,它不存在;只有当我们想要(实例化一个类型),它将强制如何构建一个结构,但在那之前我们只能用结构来论证它,< strong>设计,属性等。

注意

上面的论点(关于模板不是代码,但代码的......好模板)可能看起来有点肤浅,但从Mayer在A. Alexandrescu的书现代C ++设计中的介绍中得出了它的逻辑。那里的相对引用如下:

  

最终,Andrei将注意力转向了流行语言习语和设计模式的基于模板的实现的开发,尤其是GoF [*]模式。这导致了模式社区的短暂冲突,因为他们的一个基本原则是模式无法用代码表示。一旦很明显Andrei自动生成模式实现而不是尝试自己编码模式,那个异议就被删除了,我很高兴看到Andrei和其中一个GoF(John Vlissides)在两个专栏上合作在C ++报告中关注Andrei的工作。

答案 3 :(得分:2)

标准草案将基本类型与用户定义类型对比在几个(非规范)地方。

标准草案还使用术语&#34;用户定义&#34;在其他上下文中,指的是由标准库中定义的程序员创建的实体。示例包括用户定义的构造函数,用户定义的运算符和用户定义的转换。

根据历史用法,这些事实使我们在没有其他证据的情况下暂时假设标准的意图是用户定义的类型应该是复合类型。只有在未来的标准文件中明确说明才能解决问题。

请注意,int*struct foo*void(*)(struct foo****)等类型的历史用法并不明确。它们是复合的,但它们(或其中一些)是否应被视为用户定义的?