受模板方法声明影响的 C++ 名称查找
C++ name lookup affected by declaration of a template method
我不明白以下 C++ 代码片段(使用 GCC-4.7 测试)中 static_cast 的必要性:
#include <cstdio>
class Interface
{
public:
virtual void g(class C* intf) = 0;
virtual ~Interface() {}
};
class C
{
public:
void f(int& value)
{
printf("%d\n", value);
}
void f(Interface* i)
{
i->g(this);
}
template <typename T>
void f(T& t);
//void f(class Implementation& i);
};
class Implementation : public Interface
{
public:
Implementation(int value_) : value(value_) {}
void g(C* intf)
{
intf->f(value);
}
private:
int value;
};
int main()
{
C a;
Implementation* b = new Implementation(1);
//a.f(b); // This won't work: undefined reference to `void C::f<Implementation*>(Implementation*&)'
a.f(static_cast<Interface*>(b));
delete b;
return 0;
}
如果我省略 static_cast,我会收到链接器错误,因为它要使用:
template <typename T>
void f(T& t);
而不是:
void f(Interface* i);
另一方面,如果我将模板化方法替换为以下内容(在上面的代码段中注释掉):
void f(class Implementation& i);
然后我没有得到错误,我可以看到 "correct" 方法在 运行 时间被调用(即:
void f(Interface* i);
).
为什么模板方法的声明会影响名称查找?
非常感谢,
在为 a.f(b)
执行重载决策时,编译器注意到两个事实:
首先,您正在尝试使用 Implementation*
.
类型的左值调用 f
其次,三个函数在重载集中:C::f(int&)
和C::f(Interface*)
和C::f<Implementation*>(Implementation*&)
。请注意,包含 template
是因为它的模板参数可以从调用它的参数中推导出来。
现在编译器开始检查哪个函数适合 "best":
C::f(int&)
根本不能用这个参数调用。
C::f(Interface*)
可以被调用,但是需要一个标准的转换(指向派生的指针->指向基的指针)
C::f<Implementation*>(Implementation*&)
可以调用 无需 任何转换
因此,模板非常适合。但是,由于您没有为模板定义实现,链接器稍后会出现错误,并显示错误消息,指出它找不到您尝试调用的函数。
我不明白以下 C++ 代码片段(使用 GCC-4.7 测试)中 static_cast 的必要性:
#include <cstdio>
class Interface
{
public:
virtual void g(class C* intf) = 0;
virtual ~Interface() {}
};
class C
{
public:
void f(int& value)
{
printf("%d\n", value);
}
void f(Interface* i)
{
i->g(this);
}
template <typename T>
void f(T& t);
//void f(class Implementation& i);
};
class Implementation : public Interface
{
public:
Implementation(int value_) : value(value_) {}
void g(C* intf)
{
intf->f(value);
}
private:
int value;
};
int main()
{
C a;
Implementation* b = new Implementation(1);
//a.f(b); // This won't work: undefined reference to `void C::f<Implementation*>(Implementation*&)'
a.f(static_cast<Interface*>(b));
delete b;
return 0;
}
如果我省略 static_cast,我会收到链接器错误,因为它要使用:
template <typename T>
void f(T& t);
而不是:
void f(Interface* i);
另一方面,如果我将模板化方法替换为以下内容(在上面的代码段中注释掉):
void f(class Implementation& i);
然后我没有得到错误,我可以看到 "correct" 方法在 运行 时间被调用(即:
void f(Interface* i);
).
为什么模板方法的声明会影响名称查找? 非常感谢,
在为 a.f(b)
执行重载决策时,编译器注意到两个事实:
首先,您正在尝试使用 Implementation*
.
f
其次,三个函数在重载集中:C::f(int&)
和C::f(Interface*)
和C::f<Implementation*>(Implementation*&)
。请注意,包含 template
是因为它的模板参数可以从调用它的参数中推导出来。
现在编译器开始检查哪个函数适合 "best":
C::f(int&)
根本不能用这个参数调用。C::f(Interface*)
可以被调用,但是需要一个标准的转换(指向派生的指针->指向基的指针)C::f<Implementation*>(Implementation*&)
可以调用 无需 任何转换
因此,模板非常适合。但是,由于您没有为模板定义实现,链接器稍后会出现错误,并显示错误消息,指出它找不到您尝试调用的函数。