В последнее время я впервые обнаружил эту ошибку: invalid initialization of reference of type ‘C*&’ from expression of type ‘B*’
.Ошибка возникла при переносе кода с gcc 4.9
на gcc 6
.Ниже я вставил минимальный пример кода.
class A {
public:
A() : a(1) {};
virtual ~A() {};
int a;
};
class B : public A {
public:
B() : val(2) {};
int val;
};
class C : public A {
public:
C() : val(3) {};
float val;
};
int alloc_b(B*& entry) {
try {
entry = new B;
} catch(...) {
return -1;
}
return 0;
}
int alloc_c(C*& entry) {
try {
entry = new C;
} catch(...) {
return -1;
}
return 0;
}
template<typename T>
int whatever(const bool isB) {
T* entry = NULL;
if(isB) {
alloc_b(entry);
} else {
alloc_c(entry);
}
std::cout << entry->val << "\n";
}
int main() {
int rv;
B* ptrB;
C* ptrC;
whatever<B>(true);
whatever<C>(false);
return 0;
}
Я понимаю, что ошибка появляется, потому что при компиляции метода whatever
с isB = true
он также пытается скомпилировать также вызов alloc_c()
,поэтому он проверяет, что T = B
и не может найти какой-либо метод alloc_c(B*& entry)
, поэтому он не работаетИ другой способ invalid initialization of reference of type ‘B*&’ from expression of type ‘C*’
, когда метод whatever
вызывается с типами C
и isB = false
.
Мне было просто интересно, какой самый чистый способ обойти эту проблему.Единственное решение, которое я нашел, - это создание шаблона метода alloc
с некоторыми специализациями:
template<typename T>
int alloc(T*& entry) {
static_assert((std::is_same<decltype(entry), B>::value ||
std::is_same<decltype(entry), C>::value),
"Class must be A or B");
}
template<>
int alloc(B*& entry) {
return alloc_b(entry);
}
template<>
int alloc(C*& entry) {
return alloc_c(entry);
}
А затем внутри функции whatever
я бы вызвал это alloc вместо других allocs.
template<typename T>
int whatever(const bool isB) {
T* entry = NULL;
alloc(entry);
std::cout << entry->val << "\n";
}
Но я уверен, что должен быть более чистый способ обойти эту ошибку.