我不明白这里发生了什么。我有一个类counterexample found
,其中包含一个字段-std=c11
。现在,我创建一个扩展Base的Base
类。我还有一个模板函数,该函数通过传递指向成员的模板参数来打印我们想要的字段。
a
问题是它不起作用,但是如果我仅使用基类:
Derived
它按预期方式工作并打印#include <iostream>
class Base {
public:
Base(double a):a{a} {}
double a;
};
class Derived : public Base {
public:
Derived(double a) : Base(a) {}
};
template<double (Derived::*p)>
void print(Derived d) {
std::cout << d.*p;
}
int main() {
Derived d {10.0};
print<&Derived::a>(d);
}
。如何使它与子类一起使用?
编译器说:
template<double (Base::*p)>
void print(Base b) {
std::cout << b.*p;
}
int main() {
Base b {10.0};
print<&Base::a>(b);
}
答案 0 :(得分:0)
当仅编译器消息具有所有必须explanations的情况时,这就是示例之一:
year : Sequelize.col("episode.year")
回答评论中的问题:模板参数不能隐式转换为指向base中成员的指针,<source>: In function 'int main()':
<source>:21:23: error: no matching function for call to 'print<&Base::a>(Derived&)'
21 | print<&Derived::a>(d);
| ^
<source>:15:6: note: candidate: 'template<double Derived::* p> void print(Derived)'
15 | void print(Derived d) {
| ^~~~~
<source>:15:6: note: template argument deduction/substitution failed:
<source>:21:23: error: '&Base::a' is not a valid template argument for type 'double Derived::*'
21 | print<&Derived::a>(d);
| ^
<source>:21:23: note: because it is a member of 'Base'
Compiler returned: 1
则无济于事,因为对于指向成员的成员的模板非类型参数,必须以static_cast
的形式写(请参见https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_members)
答案 1 :(得分:0)
不是很明显,但是指向a
的成员指针的类型是double Base::*
,无论它指向a
对象还是指向Derived
的对象。 Base
个对象。您的方法仅接受Derived
参数,并且仅将指向Derived
中成员的指针作为模板参数。如果要允许不同的组合,则可以编写更多的重载。
答案 2 :(得分:0)
正如其他人解释了原因一样,我将解释解决方案:
template<typename T, double (T::*p)>
void print(T d) {
std::cout << d.*p;
}
int main() {
Derived d {10.0};
print<Base, &Base::a>(d);
}
https://gcc.godbolt.org/z/pM762f
我确定这不是您希望的,但是比重载每个版本要好。但是我认为最好是找到解决问题的更好方法,因为我知道这里的代码并不是您实际上要面对的问题,因为您可以传递双精度本身而不是成员指针。
因此,请尝试使用这种方式在代码上下文中解决问题。以下是一些可能解决您实际问题的想法(如果有的话):
enum
s std::map
是否太多constexpr
,因此您也可以在模板中使用它们)print
函数移至基类甚至派生类和许多其他解决方案,其中大多数可能对您没有帮助(因为我不知道您的代码的上下文)。