向量是“用户定义类型”吗?

时间:2021-10-03 12:59:40

In 17.6.4.2.1/1 and 17.6.4.2.1/2 of the current draft standard restrictions are placed on specializations injected by users into namespace std.

在当前草案标准限制草案的17.6.4.2.1/1和17.6.4.2.5中,将用户注入到名称空间std中。

The behavior of a C ++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

如果向名称空间std或名称空间std内的名称空间添加声明或定义,则不定义c++程序的行为,除非另有指定。只有当声明依赖于用户定义的类型,并且专门化满足原始模板的标准库要求,并且没有明确禁止时,程序才可以为任何标准库模板添加模板专门化。

I cannot find where in the standard the phrase user-defined type is defined.

我无法在标准中找到定义用户定义类型的短语。

One option I have heard claimed is that a type that is not std::is_fundamental is a user-defined type, in which case std::vector<int> would be a user-defined type.

我听到的一个选项是:is_basic是一个用户定义类型,在这种情况下std::vector 是用户定义的类型。

An alternative answer would be that a user-defined type is a type that a user defines. As users do not define std::vector<int>, and std::vector<int> is not dependent on any type a user defines, std::vector<int> is not a user-defined type.

另一种选择是用户定义的类型是用户定义的类型。由于用户不定义std::vector , std::vector 不依赖于用户定义的任何类型,std:::vector 不是用户定义的类型。

A practical problem this impacts is "can you inject a specialization for std::hash for std::tuple<Ts...> into namespace std? Being able to do so is somewhat convenient -- the alternative is to create another namespace where we recursively build our hash for std::tuple (and possibly other types in std that do not have hash support), and if and only if we fail to find a hash in that namespace do we fall back on std.

这个影响的一个实际问题是“您是否可以为std注入一个专门化::tuple 成名称空间性病吗?能够这样做很方便,另一种选择是创建另一个名称空间,我们递归构建哈希std::tuple(可能还有其他类型的性病没有散列支持),如果且仅如果我们不能找到一个散列的名称空间我们依靠性病。 …>

However, if this is legal, then if and when the standard adds a hash specialization for std::tuple to namespace std, code that specialized it already would be broken, creating a reason not to add such specializations in the future.

但是,如果这是合法的,那么当标准为std::tuple添加一个散列专门化到名称空间std时,已经专门化了的代码将被破坏,这就为以后不添加这种专门化创造了理由。

While I am talking about std::vector<int> as a concrete example, I am trying to ask if types defined in std are ever user-defined type s. A secondary question is, even if not, maybe std::tuple<int> becomes a user-defined type when used by a user (this gets slippery: what then happens if something inside std defines std::tuple<int>, and you partial-specialize hash for std::tuple<Ts...>).

当我谈论std::向量< int >作为一个具体的例子,我想问如果在性病中定义类型定义的类型。第二个问题是,即使没有,也许std::元组< int >变成一个由用户定义的类型使用时(这就滑:那么如果内心深处性病定义了std::元组< int >,你partial-specialize散列std::元组< Ts…>)。


There is currently an open defect on this problem.

目前在这个问题上有一个公开的缺陷。

4 个解决方案

#1


33  

Prof. Stroustrup is very clear that any type that is not built-in is user-defined. See the second paragraph of section 9.1 in Programming Principles and Practice Using C++.

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

He even specifically calls out “standard library types” as an example of user-defined types. In other words, a user-defined type is any compound type.

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

Source

The article explicitly mentions that not everyone seems to agree, but this is IMHO mostly wishful thinking and not what the standard (and Prof. Stroustrup) are actually saying, only what some people want to read into it.

这篇文章明确地提到,并非所有人似乎都同意,但这主要是一厢情愿的想法,而不是标准(以及斯特鲁斯特鲁普教授)实际上在说什么,而只是一些人想要读进去的东西。

#2


16  

When Clause 17 says "user-defined" it means "a type not defined in the standard" so std::vector<int> is not user-defined, neither is std::string, so you cannot specialize std::vector<int> or std::vector<std::string>. On the other hand, struct MyClass is user-defined, because it's not a type defined in the standard, so you can specialize std::vector<MyClass>.

当第17条说“用户定义”时,它的意思是“标准中没有定义的类型”,所以std::vector 不是用户定义的,std::string也不是,所以不能专门化std::vector 或std::vector 。另一方面,struct MyClass是用户定义的,因为它不是标准中定义的类型,所以可以专门化std::vector

This is not the same meaning of "user-defined" used in clauses 1-16, and that difference is confusing and silly. There is a defect report for this, with some discussion recorded that basically says "yes, the library uses the wrong term, but we don't have a better one".

这与在第1-16条中使用的“用户定义”的含义不同,这种差异令人困惑和愚蠢。这里有一个缺陷报告,记录了一些讨论,基本上说“是的,库使用了错误的术语,但是我们没有更好的术语”。

So the answer to your question is "it depends". If you're talking to a C++ compiler implementor or a core language expert, std::vector<int> is definitely a user-defined type, but if you're talking to a standard library implementor, it is not. More precisely, it's not user-defined for the purposes of 17,6.4.2.1.

所以你的问题的答案是“视情况而定”。如果您正在与c++编译器实现者或核心语言专家进行对话,那么std:::vector 肯定是用户定义的类型,但如果您正在与标准库实现者进行对话,则不是这样。更准确地说,它不是为176.4.2.1的目的而定义的用户。

One way to look at it is that the standard library is "user code" as far as the core language is concerned. But the standard library has a different idea of "users" and considers itself to be part of the implementation, and only things that aren't part of the library are "user-defined".

一种理解它的方法是,就核心语言而言,标准库是“用户代码”。但是标准库对“用户”有不同的概念,并认为自己是实现的一部分,只有不属于库的东西是“用户定义的”。

Edit: I have proposed changing the library Clauses to use a new term, "program-defined", which means something defined in your program (as opposed to UDTs defined in the standard, such as std::string).

编辑:我建议修改库子句以使用一个新术语“程序定义的”,它表示程序中定义的内容(与标准中定义的UDTs相反,比如std::string)。

#3


7  

As users do not define std::vector<int>, and std::vector<int> is not dependent on any type a user defines, std::vector<int> is not a user-defined type.

由于用户不定义std::vector , std::vector 不依赖于用户定义的任何类型,std:::vector 不是用户定义的类型。

The logical counter argument is that users do define std::vector<int>. You see std::vector is a class template and as such has no direct representation in binary code.

逻辑计数器参数是用户确实定义了std::vector 。您可以看到std::vector是一个类模板,因此在二进制代码中没有直接表示。

In a sense it gets it binary representation through the instantiation of a type, so the very action of declaring a std::vector<int> object is what gives "soul" to the template (pardon the phrasing). In a program where noone uses a std::vector<int> this data type does not exist.

在某种意义上,它通过类型的实例化来获得二进制表示,因此声明std::vector 对象的动作就是给模板“灵魂”的东西(恕我直言)。在noone使用std::vector 的程序中,这种数据类型不存在。

On the other hand, following the same argument, std::vector<T> is not a user defined type, it is not even a type, it does not exist; only if we want to (instantiate a type), it will mandate how a structure will be layed out but until then we can only argue about it in terms of structure, design, properties and so on.

另一方面,根据相同的参数,std::vector 不是用户定义的类型,它甚至不是类型,它不存在;只有当我们想要(实例化一个类型)时,它才会规定一个结构是如何被分配的,但是在此之前,我们只能从结构、设计、属性等方面来讨论它。

Note

The above argument (about templates being not code but ... well templates for code) may seem a bit superficial but draws it's logic, from Mayer's introduction in A. Alexandrescu's book Modern C++ Design. The relative quote there, goes like this :

上面的论点(关于模板不是代码,而是……)好的代码模板)可能看起来有点肤浅,但是从梅耶在a .亚历山大的书《现代c++设计》中的介绍中可以看出这是逻辑。这里的相对引用是这样的

Eventually, Andrei turned his attention to the development of template-based implementations of popular language idioms and design patterns, especially the GoF[*] patterns. This led to a brief skirmish with the Patterns community, because one of their fundamental tenets is that patterns cannot be represented in code. Once it became clear that Andrei was automating the generation of pattern implementations rather than trying to encode patterns themselves, that objection was removed, and I was pleased to see Andrei and one of the GoF (John Vlissides) collaborate on two columns in the C++ Report focusing on Andrei's work.

最终,安德烈将注意力转向了基于模板的流行语言习惯用法和设计模式的开发,特别是GoF[*]模式。这导致了与模式社区的短暂冲突,因为它们的基本原则之一是模式不能在代码中表示。一旦安德烈将模式实现的生成自动化,而不是试图对模式本身进行编码,这一反对意见就被删除了,我很高兴地看到安德烈和gandrei (John Vlissides)在c++报告的两篇专栏文章中合作,重点讨论了他的工作。

#4


2  

The draft standard contrasts fundamental types with user-defined types in a couple of (non-normative) places.

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

The draft standard also uses the term "user-defined" in other contexts, referring to entities created by the programmer or defined in the standard library. Examples include user-defined constructor, user-defined operator and user-defined conversion.

草案标准还在其他上下文中使用“用户定义”一词,指程序员创建或在标准库中定义的实体。示例包括用户定义的构造函数、用户定义的运算符和用户定义的转换。

These facts allow us, absent other evidence, to tentatively assume that the intent of the standard is that user-defined type should mean compound type, according to historical usage. Only an explicit clarification in a future standard document can definitely resolve the issue.

这些事实允许我们暂时假设标准的意图是用户定义的类型应该是复合类型,根据历史的使用情况。只有在将来的标准文档中明确说明才能解决这个问题。

Note that the historical usage is not clear on types like int* or struct foo* or void(*)(struct foo****). They are compound, but should they (or some of them) be considered user-defined?

注意,对于int*或struct foo*或void(*)(struct foo**** ***)之类的类型,历史用法并不明确。它们是复合的,但是它们(或者其中的一些)应该被认为是用户定义的吗?

#1


33  

Prof. Stroustrup is very clear that any type that is not built-in is user-defined. See the second paragraph of section 9.1 in Programming Principles and Practice Using C++.

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

He even specifically calls out “standard library types” as an example of user-defined types. In other words, a user-defined type is any compound type.

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

Source

The article explicitly mentions that not everyone seems to agree, but this is IMHO mostly wishful thinking and not what the standard (and Prof. Stroustrup) are actually saying, only what some people want to read into it.

这篇文章明确地提到,并非所有人似乎都同意,但这主要是一厢情愿的想法,而不是标准(以及斯特鲁斯特鲁普教授)实际上在说什么,而只是一些人想要读进去的东西。

#2


16  

When Clause 17 says "user-defined" it means "a type not defined in the standard" so std::vector<int> is not user-defined, neither is std::string, so you cannot specialize std::vector<int> or std::vector<std::string>. On the other hand, struct MyClass is user-defined, because it's not a type defined in the standard, so you can specialize std::vector<MyClass>.

当第17条说“用户定义”时,它的意思是“标准中没有定义的类型”,所以std::vector 不是用户定义的,std::string也不是,所以不能专门化std::vector 或std::vector 。另一方面,struct MyClass是用户定义的,因为它不是标准中定义的类型,所以可以专门化std::vector

This is not the same meaning of "user-defined" used in clauses 1-16, and that difference is confusing and silly. There is a defect report for this, with some discussion recorded that basically says "yes, the library uses the wrong term, but we don't have a better one".

这与在第1-16条中使用的“用户定义”的含义不同,这种差异令人困惑和愚蠢。这里有一个缺陷报告,记录了一些讨论,基本上说“是的,库使用了错误的术语,但是我们没有更好的术语”。

So the answer to your question is "it depends". If you're talking to a C++ compiler implementor or a core language expert, std::vector<int> is definitely a user-defined type, but if you're talking to a standard library implementor, it is not. More precisely, it's not user-defined for the purposes of 17,6.4.2.1.

所以你的问题的答案是“视情况而定”。如果您正在与c++编译器实现者或核心语言专家进行对话,那么std:::vector 肯定是用户定义的类型,但如果您正在与标准库实现者进行对话,则不是这样。更准确地说,它不是为176.4.2.1的目的而定义的用户。

One way to look at it is that the standard library is "user code" as far as the core language is concerned. But the standard library has a different idea of "users" and considers itself to be part of the implementation, and only things that aren't part of the library are "user-defined".

一种理解它的方法是,就核心语言而言,标准库是“用户代码”。但是标准库对“用户”有不同的概念,并认为自己是实现的一部分,只有不属于库的东西是“用户定义的”。

Edit: I have proposed changing the library Clauses to use a new term, "program-defined", which means something defined in your program (as opposed to UDTs defined in the standard, such as std::string).

编辑:我建议修改库子句以使用一个新术语“程序定义的”,它表示程序中定义的内容(与标准中定义的UDTs相反,比如std::string)。

#3


7  

As users do not define std::vector<int>, and std::vector<int> is not dependent on any type a user defines, std::vector<int> is not a user-defined type.

由于用户不定义std::vector , std::vector 不依赖于用户定义的任何类型,std:::vector 不是用户定义的类型。

The logical counter argument is that users do define std::vector<int>. You see std::vector is a class template and as such has no direct representation in binary code.

逻辑计数器参数是用户确实定义了std::vector 。您可以看到std::vector是一个类模板,因此在二进制代码中没有直接表示。

In a sense it gets it binary representation through the instantiation of a type, so the very action of declaring a std::vector<int> object is what gives "soul" to the template (pardon the phrasing). In a program where noone uses a std::vector<int> this data type does not exist.

在某种意义上,它通过类型的实例化来获得二进制表示,因此声明std::vector 对象的动作就是给模板“灵魂”的东西(恕我直言)。在noone使用std::vector 的程序中,这种数据类型不存在。

On the other hand, following the same argument, std::vector<T> is not a user defined type, it is not even a type, it does not exist; only if we want to (instantiate a type), it will mandate how a structure will be layed out but until then we can only argue about it in terms of structure, design, properties and so on.

另一方面,根据相同的参数,std::vector 不是用户定义的类型,它甚至不是类型,它不存在;只有当我们想要(实例化一个类型)时,它才会规定一个结构是如何被分配的,但是在此之前,我们只能从结构、设计、属性等方面来讨论它。

Note

The above argument (about templates being not code but ... well templates for code) may seem a bit superficial but draws it's logic, from Mayer's introduction in A. Alexandrescu's book Modern C++ Design. The relative quote there, goes like this :

上面的论点(关于模板不是代码,而是……)好的代码模板)可能看起来有点肤浅,但是从梅耶在a .亚历山大的书《现代c++设计》中的介绍中可以看出这是逻辑。这里的相对引用是这样的

Eventually, Andrei turned his attention to the development of template-based implementations of popular language idioms and design patterns, especially the GoF[*] patterns. This led to a brief skirmish with the Patterns community, because one of their fundamental tenets is that patterns cannot be represented in code. Once it became clear that Andrei was automating the generation of pattern implementations rather than trying to encode patterns themselves, that objection was removed, and I was pleased to see Andrei and one of the GoF (John Vlissides) collaborate on two columns in the C++ Report focusing on Andrei's work.

最终,安德烈将注意力转向了基于模板的流行语言习惯用法和设计模式的开发,特别是GoF[*]模式。这导致了与模式社区的短暂冲突,因为它们的基本原则之一是模式不能在代码中表示。一旦安德烈将模式实现的生成自动化,而不是试图对模式本身进行编码,这一反对意见就被删除了,我很高兴地看到安德烈和gandrei (John Vlissides)在c++报告的两篇专栏文章中合作,重点讨论了他的工作。

#4


2  

The draft standard contrasts fundamental types with user-defined types in a couple of (non-normative) places.

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

The draft standard also uses the term "user-defined" in other contexts, referring to entities created by the programmer or defined in the standard library. Examples include user-defined constructor, user-defined operator and user-defined conversion.

草案标准还在其他上下文中使用“用户定义”一词,指程序员创建或在标准库中定义的实体。示例包括用户定义的构造函数、用户定义的运算符和用户定义的转换。

These facts allow us, absent other evidence, to tentatively assume that the intent of the standard is that user-defined type should mean compound type, according to historical usage. Only an explicit clarification in a future standard document can definitely resolve the issue.

这些事实允许我们暂时假设标准的意图是用户定义的类型应该是复合类型,根据历史的使用情况。只有在将来的标准文档中明确说明才能解决这个问题。

Note that the historical usage is not clear on types like int* or struct foo* or void(*)(struct foo****). They are compound, but should they (or some of them) be considered user-defined?

注意,对于int*或struct foo*或void(*)(struct foo**** ***)之类的类型,历史用法并不明确。它们是复合的,但是它们(或者其中的一些)应该被认为是用户定义的吗?