我的代码中有一个函数,它只接受类成员方法作为模板参数。我需要使用从父类继承的类方法调用此方法。以下是我的问题示例代码:
template <class C>
class Test {
public:
template<typename R, R( C::* TMethod )()> // only a member function should be accepted here
void test() {}
};
class A {
public:
int a() { return 0; } // dummy method for inheritance
};
class B : public A {
public:
using A::a; // A::a should be declared in the B class declaration region
// int a() { return A::a(); } // if this lines is activated compliation works
};
int main() {
auto t = Test<B>();
t.test<int, &B::a>();
}
使用 MSVC 2019 编译器时,代码可以顺利编译。然而,使用 gcc 则会产生以下错误:
<source>: In function 'int main()':
<source>:23:23: error: no matching function for call to 'Test<B>::test<int, &A::a>()'
23 | t.test<int, &B::a>();
| ~~~~~~~~~~~~~~~~~~^~
<source>:5:10: note: candidate: 'template<class R, R (B::* TMethod)()> void Test<C>::test() [with R (C::* TMethod)() = R; C = B]'
5 | void test() {}
| ^~~~
<source>:5:10: note: template argument deduction/substitution failed:
<source>:23:17: error: could not convert template argument '&A::a' from 'int (A::*)()' to 'int (B::*)()'
23 | t.test<int, &B::a>();
|
据我所知,gcc 仍将 B::a 的类型处理为 A::a。在 cpp 参考文献中,它说:
将在其他地方定义的名称引入到此 using-declaration 出现的声明区域中。
因此,在我看来,using 应该将 A::a 方法转移到 B 的声明区域中,因此应将其处理为 B::a。我错了吗?还是 GCC 中有 bug?
以下是 Compiler Explorer 上的示例:https://godbolt.org/z/TTrd189sW
Error (active) E0304 no function template instance "Test<C>::test [with C=B]" matches argument list
。在godbolt上的MSVC版本没有问题。 - anastaciuB
中引入了name“a”,但该函数并未成为B
的成员。它的type保持不变,因为它仍然指向A
的成员。 - molbdnilousing A::a;
并不意味着“将A::a
也作为B
的成员”,而是表示“将B::a
作为A::a
的同义词使用”。 - molbdnilo