C++ 使用模板和虚函数标记疯狂
C++ tokenizing madness with templates and virtual functions
在重构一个相当大的代码库时,我的编译器想出了一个很好的方法来误解我。这是我所说内容的一个最小示例:
#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,其他人说的差不多)
这应该有效吗?
我找到的解决方法是在基础和派生 class 中声明模板化 "get"。
派生 class 中的名称 get
隐藏了基 class 中的名称 get
。因此,在执行名称查找时找不到函数模板 get()
,编译器只能按照您所见的方式解释这些标记。
您可以在 Bar
class 中使用 using
声明来解决这个问题:
class Bar : public Foo {
public:
using Foo::get;
// ^^^^^^^^^^^^^^^
virtual int get() { return 3; }
};
如果你不能修改 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。
在重构一个相当大的代码库时,我的编译器想出了一个很好的方法来误解我。这是我所说内容的一个最小示例:
#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,其他人说的差不多)
这应该有效吗?
我找到的解决方法是在基础和派生 class 中声明模板化 "get"。
派生 class 中的名称 get
隐藏了基 class 中的名称 get
。因此,在执行名称查找时找不到函数模板 get()
,编译器只能按照您所见的方式解释这些标记。
您可以在 Bar
class 中使用 using
声明来解决这个问题:
class Bar : public Foo {
public:
using Foo::get;
// ^^^^^^^^^^^^^^^
virtual int get() { return 3; }
};
如果你不能修改 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。