将指向 T 的指针存储在 void* 中,但 T 可以是常量或非常量 - 使用 void const* 还是仅使用 void*?
Storing a pointer to T in a void* but T may be const or nonconst - use void const* or just void*?
当模板代码需要将 T*
存储在类型为 void*
的变量中以便稍后可以检索并转换回 T*
时,但它需要处理T
和 T const*
,它应该使用 void*
还是 void const*
作为类型擦除存储? (任一选择都需要在某处至少进行一次 const 转换。)
(假设程序在运行时跟踪放入 void* 的内容,以确保它只检索与放入的内容相同的类型,但在编译时不知道将存储什么类型在变量中。)
编辑:还假设非类型化存储隐藏在包装器 class 后面,该包装器具有模板化的 set() 和 get() 方法,记录了用于 set() 调用的 T 和如果不同的 T 用于 get(),则抛出异常。所以问题实际上是关于包装器 class 应该如何存储它。 (注意:包装器 class 本身不是模板;只是它的方法 set() 和 get() 是模板。)
以前遇到这个问题时,我用过union { void* p_nc; void const* p_c; };
。但是我想知道与仅使用 const_cast.
相比这是否有点矫枉过正
问题是,哪种方法更好(如果有的话):在 void*
中存储时将 const 关闭 T const*
,或者使用 void* const
进行存储并转换const off 如果检索非常量 T*
?
从将要阅读您的代码的人(甚至是未来 6 个月后的您)的角度来看,最好尽可能清楚地表达您的想法,而不是试图尽量减少代码的数量你施放的次数。
在您使用 union
的情况下,表示 "it can be either one" 但它不会对实际执行其用法进行任何检查。
OTOH 具有清晰的接口,可实现 const 和 non-const 访问函数(包括转换函数),允许您执行 runtime-check 并采取相应行动(错误消息?异常?)。
清晰的接口还有一个额外的好处,那就是封装实现,这样您的客户端代码就不会依赖于实现的内部结构 - 您的客户端代码将只使用您的模板作为 const 或 non-const (取决于用法)和 access/cast 函数将负责确保用法实际有效。
当模板代码需要将 T*
存储在类型为 void*
的变量中以便稍后可以检索并转换回 T*
时,但它需要处理T
和 T const*
,它应该使用 void*
还是 void const*
作为类型擦除存储? (任一选择都需要在某处至少进行一次 const 转换。)
(假设程序在运行时跟踪放入 void* 的内容,以确保它只检索与放入的内容相同的类型,但在编译时不知道将存储什么类型在变量中。)
编辑:还假设非类型化存储隐藏在包装器 class 后面,该包装器具有模板化的 set() 和 get() 方法,记录了用于 set() 调用的 T 和如果不同的 T 用于 get(),则抛出异常。所以问题实际上是关于包装器 class 应该如何存储它。 (注意:包装器 class 本身不是模板;只是它的方法 set() 和 get() 是模板。)
以前遇到这个问题时,我用过union { void* p_nc; void const* p_c; };
。但是我想知道与仅使用 const_cast.
问题是,哪种方法更好(如果有的话):在 void*
中存储时将 const 关闭 T const*
,或者使用 void* const
进行存储并转换const off 如果检索非常量 T*
?
从将要阅读您的代码的人(甚至是未来 6 个月后的您)的角度来看,最好尽可能清楚地表达您的想法,而不是试图尽量减少代码的数量你施放的次数。
在您使用 union
的情况下,表示 "it can be either one" 但它不会对实际执行其用法进行任何检查。
OTOH 具有清晰的接口,可实现 const 和 non-const 访问函数(包括转换函数),允许您执行 runtime-check 并采取相应行动(错误消息?异常?)。
清晰的接口还有一个额外的好处,那就是封装实现,这样您的客户端代码就不会依赖于实现的内部结构 - 您的客户端代码将只使用您的模板作为 const 或 non-const (取决于用法)和 access/cast 函数将负责确保用法实际有效。