所以,我有一个模板类,它必须在某个时候调用回调函数。该回调函数将const T
模板作为参数。
我将该函数的指针传递给模板类Boom<void*>
。但是,该回调的const T
参数仅被解释为T
。
但只有void*
才会出现这种情况。
代码:
//main.cpp
void kolbek(const void* val)
{
if(val)
printf("Value is: %d\n", *((int*)val));
else
printf("Value ptr = NULL\n");
}
int main()
{
Boom<void*> bomba;
bomba.setCallback(kolbek); //error!
int* nuint = new int(5);
bomba.callCallback((void*)nuint);
delete nuint;
return 0;
}
// boom.h
template<typename T>
class Boom
{
private:
void (*someCallback)(const T) = nullptr;
public:
Boom(){ }
~Boom(){ }
void setCallback(void (*callbk)(const T));
void callCallback(const T val);
};
// boom.cpp
template<typename T>
void Boom<T>::setCallback(void (*callbk)(const T))
{
this->someCallback = callbk;
}
template<typename T>
void Boom<T>::callCallback(const T val)
{
if(someCallback)
(*someCallback)(val);
else
printf("Bad! Callback's NULL!\n");
}
template class Boom<int>;
template class Boom<void*>;
在尝试编译时,会抛出错误:
error: invalid conversion from 'void (*)(const void*)' to 'void (*)(void*)' [-fpermissive]
error: initializing argument 1 of 'void Boom<T>::setCallback(void (*)(T)) [with T = void*]' [-fpermissive]
如何解决?似乎只有void *指针被错误解释。
答案 0 :(得分:1)
在注释中提到的情况下,您可以创建帮助器结构以使模板解除引用参数const:
template<class T>
struct ptr_constantizer {
using type = const T;
};
template<class T>
struct ptr_constantizer<T*> {
using type = const T*;
};
template<typename T>
class Boom
{
private:
void (*someCallback)(typename ptr_constantizer<T>::type) = nullptr;
public:
Boom(){ }
~Boom(){ }
void setCallback(void (*callbk)(typename ptr_constantizer<T>::type)) { }
void callCallback(const T val) { }
};
void foo(const void *ptr) {
}
void fooi(const int non_ptr) {
}
int main() {
Boom<void *> b;
Boom<int> bi;
b.setCallback(&foo);
bi.setCallback(&fooi);
}
代码假设您使用c++11
,因为您在示例中使用了nullptr
...
答案 1 :(得分:1)
你的问题来自混淆两个不同的const
。这就是为什么写T const
代替const T
会有所帮助 - 它使文字替换不属于你。
Boom
的回调需要T const
,其中你的实例是void* const
(不是const void*
!!):它是指向非const
的指针const
void
。 kolbek
的参数采用void const*
- 指向const void
的指针。那些不是同一类型。你可以进行从前者到后者的资格转换,但不是相反(你要抛弃const
!)。这是您的编译器错误。
最简单的解决方案并非Boom
添加const
。这是不必要的。使用提供的T
并使用Boom<const void*>
。