<Inside The C++ Object Model> 中的模板分辨率
Template Resolution in <Inside The C++ Object Model>
在"Inside the C++ Object Model,"的第7章中写到,nomember name的解析取决于name的使用是否与"the type of parameter used to instantiate the template."相关
我写一个测试:
/// -------------Test.h---------------
#ifndef TEST_H
#define TEST_H
#include <iostream>
using namespace std;
extern double foo(double t);
template <typename T>
class Test {
public:
void fun1() {
member = foo(val);
}
T fun2() {
return foo(member);
}
private:
int val;
T member;
};
#endif
和
/// -------------test1.cc-------------
#include <iostream>
using namespace std;
double foo(double t) {
cout << "foo doule is called" << endl;
return t;
}
int foo(int t) {
cout << "foo int is called" << endl;
return t;
}
-------------test.cc--------------
#include "Test.h"
extern int foo(int t);
int main() {
Test<int> fi;
fi.fun1();
fi.fun2();
return 0;
}
我希望“foo double 是 called\n
foo int 被称为",
但我得到“foo double is called\n
foo double 被称为“。
我的 g++ 版本如下。如果你能帮助我,我将不胜感激。
恐怕这本书没有描绘出完整的画面(而且有点陈旧)。是的,foo(member)
是依赖于模板参数的函数调用。但是在模板中查找函数的具体方式在 C++ 标准中有描述 [temp.dep.candidate]:
For a function call where the postfix-expression is a dependent name,
the candidate functions are found using the usual lookup rules
([basic.lookup.unqual], [basic.lookup.argdep]) except that:
- For the part of the lookup using unqualified name lookup, only function declarations from the template definition context are found.
- For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either
the template definition context or the template instantiation context
are found.
foo
的重载可以通过以下两种方式之一查找。通过直接不合格查找和 argument dependent lookup(又名 ADL)。简单的非限定查找仅考虑在模板定义点已知的名称。由于您只声明了 foo(double)
,这是在模板定义点发现的唯一重载。
在实例化时,编译器 将 尝试执行 ADL 以查找更多 foo
,但基本类型对 ADL 没有贡献。 int
不能用于查找 foo(int)
。所以编译器只能做一件事,将整数转换为双精度数,然后调用 foo(double)
.
如果您想测试您的编译器 ADL,您只需添加一个简单的用户定义类型和重载。例如:
enum E{};
E foo(E) {
cout << "foo E is called\n";
return {};
}
int main() {
Test<E> fi;
fi.fun1();
fi.fun2();
return 0;
}
在"Inside the C++ Object Model,"的第7章中写到,nomember name的解析取决于name的使用是否与"the type of parameter used to instantiate the template."相关 我写一个测试:
/// -------------Test.h---------------
#ifndef TEST_H
#define TEST_H
#include <iostream>
using namespace std;
extern double foo(double t);
template <typename T>
class Test {
public:
void fun1() {
member = foo(val);
}
T fun2() {
return foo(member);
}
private:
int val;
T member;
};
#endif
和
/// -------------test1.cc-------------
#include <iostream>
using namespace std;
double foo(double t) {
cout << "foo doule is called" << endl;
return t;
}
int foo(int t) {
cout << "foo int is called" << endl;
return t;
}
-------------test.cc--------------
#include "Test.h"
extern int foo(int t);
int main() {
Test<int> fi;
fi.fun1();
fi.fun2();
return 0;
}
我希望“foo double 是 called\n foo int 被称为", 但我得到“foo double is called\n foo double 被称为“。 我的 g++ 版本如下。如果你能帮助我,我将不胜感激。
恐怕这本书没有描绘出完整的画面(而且有点陈旧)。是的,foo(member)
是依赖于模板参数的函数调用。但是在模板中查找函数的具体方式在 C++ 标准中有描述 [temp.dep.candidate]:
For a function call where the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) except that:
- For the part of the lookup using unqualified name lookup, only function declarations from the template definition context are found.
- For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either the template definition context or the template instantiation context are found.
foo
的重载可以通过以下两种方式之一查找。通过直接不合格查找和 argument dependent lookup(又名 ADL)。简单的非限定查找仅考虑在模板定义点已知的名称。由于您只声明了 foo(double)
,这是在模板定义点发现的唯一重载。
在实例化时,编译器 将 尝试执行 ADL 以查找更多 foo
,但基本类型对 ADL 没有贡献。 int
不能用于查找 foo(int)
。所以编译器只能做一件事,将整数转换为双精度数,然后调用 foo(double)
.
如果您想测试您的编译器 ADL,您只需添加一个简单的用户定义类型和重载。例如:
enum E{};
E foo(E) {
cout << "foo E is called\n";
return {};
}
int main() {
Test<E> fi;
fi.fun1();
fi.fun2();
return 0;
}