是std :: vector <T>一个`用户定义的types`?
在当前标准草案的 17.6.4.2.1 / 1和17.6.4.2.1 / 2中,对用户注入namespace std
专门化进行了限制。
除非另有说明,否则C ++程序的行为是未定义的,如果它将声明或定义添加到名称空间std或名称空间std中的名称空间。 只有当声明依赖于用户定义的types ,并且专业化符合原始模板的标准库要求并且没有明确禁止时,程序可以将任何标准库模板的模板专用化添加到名称空间std。
我无法find标准中用户定义types定义的词组。
我听说一个选项声称是一个不是std::is_fundamental
types是一个用户定义的types ,在这种情况下, std::vector<int>
将是一个用户定义的types 。
另一个答案是用户定义的types是用户定义的types 。 由于用户没有定义std::vector<int>
,而std::vector<int>
不依赖于用户定义的任何types,所以std::vector<int>
不是用户定义的types 。
这个影响的一个实际问题是“你可以为std::tuple<Ts...>
注入一个std::hash
的专门化到namespace std
吗?能够这样做有点方便 – 另一种方法是创build另一个名称空间我们recursion地构build我们的std::tuple
(也可能是std
中没有hash
支持的其他types)的hash
,当且仅当我们无法在那个名字空间中find散列时,我们才回退std
。
但是,如果这是合法的,那么如果标准为std::tuple
添加了一个hash
专门化到namespace std
,已经被专门化的代码将被破坏,创build一个不会在未来添加这样的专业化的理由。
虽然我正在谈论作为一个具体的例子std::vector<int>
,我想问是否std
中定义的types是用户定义的types s。 第二个问题是,即使没有,也许std::tuple<int>
在用户使用时变成了一个用户定义的types (这会变得很滑:如果std
内的东西定义了std::tuple<int>
,那么会发生什么呢?你对std::tuple<Ts...>
进行部分hash
)。
目前在这个问题上有一个公开的缺陷 。
Stroustrup教授非常清楚,任何不是内置的types都是用户定义的 。 请参阅使用C ++编程原理和实践中第9.1节的第二段。
他甚至专门叫出“标准库types”作为用户定义types的一个例子。 换句话说,用户定义的types是任何复合types。
资源
文章明确提到,并不是每个人都同意,但这是恕我直言大多是一厢情愿的想法,而不是标准(和斯特劳斯楚普教授)实际上是说什么,只有一些人想要读到它。
当第17章说“用户定义”意味着“一个没有在标准中定义的types”,所以std::vector<int>
不是用户定义的,既不是std::string
,所以你不能专门化std::vector<int>
或std::vector<std::string>
。 另一方面, struct MyClass
是用户定义的,因为它不是标准中定义的types,所以你可以专门化std::vector<MyClass>
。
这与第1-16条中使用的“用户定义”不同,这个区别是混乱而愚蠢的。 这里有一个缺陷报告 ,有一些讨论logging,基本上说“是的,图书馆使用错误的术语,但我们没有更好的”。
所以你的问题的答案是“这取决于”。 如果您正在与C ++编译器实现者或核心语言专家交谈,则std::vector<int>
绝对是用户定义的types,但如果您正在与标准库实现者交谈,则不是。 更确切地说, 对于17,6.4.2.1而言 ,它不是用户定义的 。
一种看待它的方式是就核心语言而言,标准库是“用户代码”。 但标准库对“用户”有不同的看法,认为自己是实现的一部分,只有不属于图书馆一部分的东西才是“用户自定义的”。
编辑:我build议改变库的子句,使用一个新的术语,“程序定义”,这意味着在您的程序中定义的东西(而不是标准中定义的UDTs,如std::string
)。
由于用户没有定义
std::vector<int>
,而std::vector<int>
不依赖于用户定义的任何types,所以std::vector<int>
不是用户定义的types。
逻辑反参数是用户定义std::vector<int>
。 你看std::vector
是一个类模板 ,因此在二进制代码中没有直接的表示。
从某种意义上讲,它通过实例化一个types来获得二进制表示,所以声明一个std::vector<int>
对象的行为就是给模板“灵魂”(赦免措辞)。 在没有人使用std::vector<int>
的程序中,这个数据types不存在。
另一方面,遵循相同的参数, std::vector<T>
不是用户定义的types,它甚至不是一个types,它不存在; 只有当我们想要(实例化一个types)时, 才会要求一个结构如何布局,但是在那之前我们只能从结构 , devise , 属性等方面来进行讨论。
注意
Mayer在A. Alexandrescu的“ Modern C ++ Design”一书中介绍了上述观点(关于模板不是代码,而是代码模板)可能看起来有点肤浅, 那里的相关引用是这样的:
最后,Andrei把注意力转向开发基于模板的stream行语言习语和devise模式,尤其是GoF模式。 这导致了与Patterns社区的短暂冲突, 因为他们的基本原则之一是模式不能用代码表示。 一旦变得清晰,Andrei自动化了模式实现的生成,而不是自己编码模式 ,这个反对意见就被删除了,我很高兴看到Andrei和GoF(John Vlissides)之一在C ++报告关注安德烈的工作。
标准草案在几个(非规范的)地方将基本types与用户定义types进行了对比。
标准草案还在其他上下文中使用术语“用户定义”,指由程序员创build或在标准库中定义的实体。 示例包括用户定义的构造函数,用户定义的运算符和用户定义的转换。
这些事实使我们在缺乏其他证据的情况下,暂时假定标准的意图是根据历史用法,用户定义types应该是复合types。 只有在未来的标准文件中明确澄清,才能明确解决问题。
请注意,历史用法在像int*
或struct foo*
或void(*)(struct foo****)
这样的types上是不清楚的。 他们是复合的,但他们(或其中一些)应该被视为用户定义?