Yak*_*ont 40 c++ template-specialization language-lawyer c++11 c++14
在当前草案的 17.6.4.2.1/1和17.6.4.2.1/2中,标准限制是针对用户注入的专业化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
to 添加了特殊化namespace std
,那么专用它的代码就会被破坏,从而创建一个不再添加此类特化的理由.
虽然我所说的std::vector<int>
是一个具体的例子,但我试图询问定义的类型std
是否是用户定义的类型.次要问题是,就算没有,也许std::tuple<int>
成为一个用户定义类型用户使用时(这得到滑:那么,什么会发生,如果里面的东西std
定义std::tuple<int>
,你局部专门hash
为std::tuple<Ts...>
).
目前这个问题存在缺陷.
Dan*_*rey 33
Stroustrup教授非常清楚,任何非内置类型都是用户定义的.请参阅使用C++编程原理和实践中第9.1节的第二段.
他甚至特意将"标准库类型"称为用户定义类型的示例.换句话说,用户定义的类型是任何复合类型.
文章明确提到不是每个人似乎都同意,但这是恕我直言,主要是一厢情愿的想法,而不是标准(和Stroustrup教授)实际上说的是什么,只有一些人想要读到它.
Jon*_*ely 16
当第17条说,"用户自定义",它的意思是"在标准中定义的类型"这样std::vector<int>
是不是用户定义的,也不是std::string
,所以你不能专注std::vector<int>
或std::vector<std::string>
.另一方面,struct MyClass
用户定义,因为它不是标准中定义的类型,所以你可以专门化std::vector<MyClass>
.
这与第1-16条中使用的"用户定义"的含义不同,这种差异令人困惑和愚蠢.有一个缺陷报告,有一些讨论记录,基本上说"是的,图书馆使用错误的术语,但我们没有更好的术语".
所以你的问题的答案是"它取决于".如果您正在与C++编译器实现者或核心语言专家std::vector<int>
交谈,那么肯定是用户定义的类型,但如果您正在与标准库实现者交谈,则不是.更确切地说,它不是用于17,6.4.2.1目的的用户定义.
一种看待它的方法是,就核心语言而言,标准库是"用户代码".但是标准库对"用户"有不同的看法,并认为自己是实现的一部分,只有不属于库的东西才是"用户定义的".
编辑:我建议更改库子句使用新术语"程序定义",这意味着在程序中定义的东西(与标准中定义的UDT相反,例如std::string
).
由于用户未定义
std::vector<int>
,并且std::vector<int>
不依赖于用户定义的任何类型,std::vector<int>
因此不是用户定义的类型.
逻辑相反的观点是,用户就定义std::vector<int>
.您看到的std::vector
是一个类模板,因此在二进制代码中没有直接表示.
从某种意义上说,它通过一个类型的实例化获得二进制表示,因此声明一个std::vector<int>
对象的动作就是给模板提供"灵魂"(原谅措辞).在没有人使用std::vector<int>
此数据类型的程序中不存在.
在另一方面,下面的相同的参数,std::vector<T>
是不是用户定义的类型,它甚至不是一个类型,它不存在; 只有当我们想要(实例化一个类型)时,它才会强制建立一个结构,但在此之前我们只能在结构,设计,属性等方面争论它.
上面的论点(关于模板不是代码,但......代码的好模板)可能看起来有点肤浅,但从Mayer在A. Alexandrescu的书" Modern C++ Design"中的介绍中得出了它的逻辑.那里的相对引用如下:
最终,Andrei将注意力转向了流行语言习语和设计模式的基于模板的实现的开发,尤其是GoF [*]模式.这导致了与Patterns社区的短暂冲突,因为他们的一个基本原则是模式无法用代码表示.一旦很明显Andrei自动生成模式实现而不是尝试自己编码模式,那个异议就被删除了,我很高兴看到Andrei和其中一个GoF(John Vlissides)在C++报告的两个专栏上合作专注于安德烈的工作.