C用模板和虚函数标记疯狂
作者:互联网
在重构一个相当大的代码库的过程中,我的编译器想出了一个误解我的好方法.这是我所说的最简单的例子:
#include <iostream>
class Foo {
public:
virtual int get() = 0;
template <typename T> int get(int i) { return 4 + i; }
};
class Bar : public Foo {
public:
virtual int get() { return 3; }
};
int main(int argv, char **argc) {
Bar b;
std::cout << b.get<char>(7) << std::endl;
return 0;
}
Clang 3.6,gcc 4.7,gcc 4.8和gcc 4.9都将“b.get(7)”标记为“b.get”和“char”之间的比较运算符.
template-test.cpp: In function ‘int main(int, char**)’:
template-test.cpp:16:17: error: invalid use of non-static member function
std::cout << b.get<char>(7) << std::endl;
^
template-test.cpp:16:21: error: expected primary-expression before ‘char’
std::cout << b.get<char>(7) << std::endl;
^
(这是gcc 4.9,其他人说类似的东西)
这应该有用吗?
我找到的解决方法是在基类和派生类中声明模板化的“get”.
解决方法:
派生类中的名称get隐藏了基类中的名称get.因此,在执行名称查找时找不到函数模板get(),并且编译器只能以您看到的方式解释这些令牌.
您可以在Bar类中使用using声明来修复它:
class Bar : public Foo {
public:
using Foo::get;
// ^^^^^^^^^^^^^^^
virtual int get() { return 3; }
};
这是一个live demo on Coliru.
如果您无法修改Bar的定义,因为它不在您的控制之下,我猜您可以将调用限定为get():
std::cout << f.Foo::get<char>(7) << std::endl; // get() template is found now.
有关现场演示,请参阅here.另一种选择是通过指针或对Foo的引用来执行调用:
Bar b;
Foo& f = b;
std::cout << f.get<char>(7) << std::endl; // get() template is found now.
再一次,live example.
标签:c,templates,g,clang-2 来源: https://codeday.me/bug/20190722/1505373.html