这是一个非常愚蠢的示例,是我在Windows中使用线程将const_cast
和static_cast
包装到一个线程时出现的
// Somewhere in the OS API
using function_t = void(*)(void *);
void create_thread(function_t function, void *params);
template <typename T, typename U>
T static_const_cast(U ptr) {
return const_cast<T>(static_cast<const T>(ptr));
}
void thread_proc(const void* name) {
// ...
}
void test() {
const char *name = "name";
void *params = static_const_cast<void *>(name); // Fails
// void *params = const_cast<void *>(static_cast<const void *>(name));
// Succeeds (what I want to achieve with static_const_cast)
create_thread(reinterpret_cast<function_t>(thread_proc), params);
}
但是它无法在Visual Studio 2017上编译,因此我在Godbolt上尝试了gcc和clang,认为它应该可以编译,但仍然拒绝错误消息(来自gcc 8.2):< / p>
error: invalid static_cast from type 'const char*' to type 'void* const'
^^^^^^^^^^^^^
为什么它会尝试强制转换为void* const
而不是预期的const void*
?有什么明显的我想念的吗?
答案 0 :(得分:3)
为什么此函数将'const char *'强制转换为'void * const'而不是'const void *'
因为您使用void *
作为模板参数,并且在将const应用于模板参数时,它变为void * const
。 void *
是一个指针(指向非const对象),将指针设为const会得到const指针,而不是指向const对象的(非const)指针。
您可以执行以下操作来实现所需的目标:
return const_cast<T>(
static_cast<std::remove_pointer_t<T> const*>(ptr)
);
但是,我建议改用自定义类包装发送到线程的数据。另外,请勿强制转换函数类型。将函数与void*
参数一起使用,并将参数转换为函数。
struct params_t {
const char *name;
};
static params_t params {"name"};
create_thread(thread_proc, ¶ms);
不需要任何强制转换(显然在回调中除外)。