Is std :: vector <T> a "user-defined type"?
In 17.6.4.2.1 / 1 and 17.6.4.2.1 / 2 the current draft standard sets restrictions on the specializations entered by users in namespace std .
The behavior of a C ++ program is undefined if it adds declarations or definitions to the standard namespace or the namespace in the standard namespace unless otherwise specified. The program can add a template specialization for any standard library template for the standard namespace only if the declaration depends on the user type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.
I cannot find where the phrase defines a user-defined type in the standard.
One of the options I've heard about is that the type std::is_fundamental not a user-defined type , in which case std::vector<int> will be a user-defined type .
An alternative answer would be that the user type is the type that the user defines. Because users do not define std::vector<int> , and std::vector<int> is independent of any type that the user defines, std::vector<int> not a user-defined type .
The practical problem is that "can you introduce a specialization for std::hash for std::tuple<Ts...> in the namespace std ? The ability to do this is somewhat convenient - the alternative is to create another namespace in which we recursively we create our hash for std::tuple (and possibly other types in std that do not have hash support), and if and only if we cannot find the hash in this namespace, we return to std .
However, if this is legal, then if and when the standard adds a hash specialization for std::tuple to the namespace std , the code that specialized it will be violated, creating a reason not to add such specializations in the future.
While I'm talking about std::vector<int> as a concrete example, I'm trying to ask if the types defined in std are a user-defined type . The second question, even if not, maybe std::tuple<int> becomes a user-defined type when used by the user (this gets slippery: what happens if something inside std defines std::tuple<int> and you partially specialized hash for std::tuple<Ts...> ).
There is currently a problem opening a defect on this problem.
Prof. Stroustrup is very clear that any type that is not inline is user-defined. See the second paragraph of Section 9.1, "Principles and Practices for Programming Using C ++".
It even specifically calls "standard library types" as an example of custom types. In other words, a custom type is any composite type.
The article explicitly mentions that not everyone seems to agree, but this IMHO is basically wishful thinking, and not what the standard (and Prof. Straustrup) actually says, only what some people want to read in it .
When “user-defined” is specified in section 17, it means “a type not defined in the standard”, therefore std::vector<int> is not a user, not std::string , therefore you cannot specialize std::vector<int> or std::vector<std::string> . On the other hand, struct MyClass is user-defined because it is not a type defined in the standard, so you can specialize std::vector<MyClass> .
This is not the same meaning as “custom” used in paragraphs 1–16, and this difference is confusing and stupid. There is a defect report for this, with some discussion that basically says: "Yes, the library uses the wrong term, but we do not have the best."
So, the answer to your question is "it depends." If you are talking to a C ++ compiler developer or a core language specialist, std::vector<int> definitely a user-defined type, but if you are talking to a standard library developer, it is not. More precisely, it is not defined by the user for the purposes of 17.6.4.2.1.
One way to look at this is that the standard library is a “user code” in relation to the main language. But the standard library has a different idea of "users" and considers itself to be part of the implementation, and only those things that are not part of the library are "user-defined".
Edit: I suggested changing the library Clauses to use the new term "with software definition", which means something specific in your program (unlike UDT defined in the standard, for example std::string ).
Because users do not define
std::vector<int>, andstd::vector<int>is independent of any type that the user defines,std::vector<int>not a user-defined type.
The logical counter argument is that do users define std::vector<int> . You see that std::vector is a class template and as such does not have a direct representation in binary.
In a sense, it gets this binary representation through an instance of the type, so the very act of declaring an object std::vector<int> is what gives the "soul" to the template (pardoning a phrase). In a program where no one uses std::vector<int> , this data type does not exist.
On the other hand, for the same argument, std::vector<T> is a non- user defined type, it is not even a type, it does not exist; only if we want (to create an instance of the type), it will highlight how the structure will be laid out, but before that we can only state this in terms of structure , design , properties , etc.
Note
The above argument (about templates, not about code, but ... templates for code) may seem a bit superficial, but makes it logical, starting with Mayer's introduction to Alexander Alexandrescu’s book Modern C ++ Design . The relative quote there is as follows:
In the end, Andrew drew attention to the development of template implementations of popular language idioms and design templates, especially GoF templates [*]. This led to a brief hassle with the Patterns community , because one of their basic principles is that patterns cannot be represented in code. As soon as it became clear that Andrei automated the creation of template implementations, rather than trying to encode the templates themselves , this objection was removed, and I was glad to see that Andrei and one of GoF (John Vlissides) collaborate on two columns in the C ++ report, dedicated to the work of Andrew.
The draft standard contrasts basic types with custom types in several (non-normative) places.
The project standard also uses the term "user-defined" in other contexts, referring to objects created by the programmer or defined in the standard library. Examples include a custom constructor, a custom operator, and a custom transform.
These facts allow us, apart from other evidence, to tentatively assume that the purpose of the standard is that a user-defined type should mean a composite type, according to historical usage. Only a clear explanation in a future standard document can definitely solve the problem.
Note that historical usage is unclear in types like int* or struct foo* or void(*)(struct foo****) . They are complex, but should they (or some of them) be considered user-defined?