- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
考虑这段代码:
struct A; // incomplete type
template<class T>
struct D { T d; };
template <class T>
struct B { int * p = nullptr; };
int main() {
B<D<A>> u, v;
u = v; // doesn't compile; complain that D<A>::d has incomplete type
u.operator=(v); // compiles
}
Demo .从 u.operator=(v)
编译但 u = v;
不是,在后一个表达式的重载解析期间,编译器必须隐式实例化 D<A>
- 但我不明白为什么需要实例化。
为了让事情更有趣,这段代码编译:
struct A; // incomplete type
template<class T>
struct D; // undefined
template <class T>
struct B { int * p = nullptr; };
int main() {
B<D<A>> u, v;
u = v;
u.operator=(v);
}
Demo .
这里发生了什么?为什么u = v;
导致 D<A>
的隐式实例化- B
的正文中没有使用的类型的定义——在第一种情况下,而不是第二种情况?
最佳答案
整件事的重点是ADL开始:
N3797 - [basic.lookup.argdep]
When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered during the usual unqualified lookup (3.4.1) may be searched, and in those namespaces, namespace-scope friend function or function template declarations (11.3) not otherwise visible may be found.
以下:
For each argument type T in the function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes to be considered. [...] The sets of namespaces and classes are determined in the following way:
- If T is a class type [..] its associated classes are: ... furthemore if T is a class template specialization its associated namespaces and classes also include: the namespaces and classes associated with the types of the template arguments provided for template type parameters
D<A>
是一个关联类,因此在列表中等待轮到它。
现在是有趣的部分 [temp.inst]/1
Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated [...] when the completeness of the class type affects the semantics of the program
可以认为 D<A>
类型的完整性完全不影响该程序的语义,但是 [basic.lookup.argdep]/4 说:
When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier (3.4.3.2) except that:
[...] Any namespace-scope friend functions or friend function templates declared in associated classes are visible within their respective namespaces even if they are not visible during an ordinary lookup (11.3)
即类类型的完整性实际上会影响 friend 声明 -> 类类型的完整性因此会影响程序的语义。这也是您的第二个示例有效的原因。
TL;DR D<A>
被实例化了。
最后一个有趣的点是为什么 ADL 首先是为了
u = v; // Triggers ADL
u.operator=(v); // Doesn't trigger ADL
§13.3.1.2/2 规定不能有非成员(member) operator=
(内置的除外)。加入 [over.match.oper]/2:
The set of non-member candidates is the result of the unqualified lookup of operator@ in the context of the expression according to the usual rules for name lookup in unqualified function calls (3.4.2) except that all member functions are ignored.
逻辑结论是:如果表 11 中没有非成员形式,则执行 ADL 查找毫无意义。但是 [temp.inst]p7 放宽了这一点:
If the overload resolution process can determine the correct function to call without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.
这就是 clang 触发整个 ADL -> implicit instantiation
的原因。首先处理。
从 r218330 开始(在撰写本文时,它已在几分钟前提交)此行为已更改为不对 operator=
执行 ADL完全没有。
引用文献
感谢 Richard Smith 和 David Blaikie 帮助我解决这个问题。
关于c++ - gcc 和 clang 在运算符重载解析期间隐式实例化模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25925551/
假设我有一个类,我在其中重载了运算符 == : Class A { ... public: bool operator== (const A &rhs) const; ... };
我知道你不应该使用 std::find(some_map.begin(), some_map.end()) 或 std::lower_bound,因为它会采用线性时间而不是 some_map.lowe
我正在尝试在 Haskell 中定义 Vector3 数据类型,并允许在其上使用 (+) 运算符。我尝试了以下方法: data Vector3 = Vector3 Double Double Doub
我已经为我的类图将运算符重载为“-”。它的用途并不完全直观(糟糕的编码 - 我知道)但是如果我做 graph3 = graph2-graph1 那么图 3 是应该只接收图 2 和图 1 中的那些顶点。
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Operator overloading 我想重载 以按字母顺序排列字符串,但我不确定该怎么做。 如何再次
下面的代码给我一个编译错误。谁能告诉我为什么? class mytype { public: int value; mytype(int a) { value = a;
这有什么问题吗? class Vec2 attr_accessor :x, :y # ... def += (v) @x += v.x @y += v.y retu
是否可以重载 [] 运算符两次?允许这样的事情:function[3][3](就像在二维数组中一样)。 如果可能的话,我想看看一些示例代码。 最佳答案 您可以重载 operator[] 以返回一个对象
我的团队目前正在与 Lua 合作,创建一个 android 游戏。我们遇到的一件事是表面上无法创建重载构造函数。 我习惯于使用默认值设置一个对象,然后在需要时使其过载。 前任: apples() {
我有一个网页,在某个时候显示一个导航栏,它只不过是一个 a 元素的列表 (ul)。所述 a 元素的大多数样式规则都是通用的。唯一应该改变的部分是要显示的图像,可以从列表中每个 li 元素的 id 标签
我对使用/重载“范围步长”运算符(.. ..)很感兴趣,但我终其一生都无法了解如何使用它。 在文档中它说 // Usage: start .. step .. finish 但是在 F# shell
Java 11(可能无关紧要): public static String toString(Object obj) { return ReflectionToStringBuilder.to
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我无法理解以下代码(针对行号进行注释) class Base { void m1(Object o) { } void m2(String o) { } } publi
我有以下代码片段: #include using namespace std; struct Integer{ int x; Integer(const int val) : x(v
class myclass{ //definitions here }; myclass e; int myarray[10]; /* Do something... */ e = myarray;
为什么不能将下标运算符(operator [])作为 friend 函数重载? 最佳答案 正如Bjarne Stroustrup在D&E book中所说: However, even in the o
我有以下代码片段: #include using namespace std; struct Integer{ int x; Integer(const int val) : x(v
因此,我有一个问题是我最近尝试重载 namespace Eng { /** * A structure to represent pixels */ typedef
如何重载onResume()以正确的方式工作?我想从 activity 返回到 MainActivity ,我希望在其中具有与应用程序启动后相同的状态。我想使用 recreate() 但它循环了或者类
我是一名优秀的程序员,十分优秀!