【问题标题】:reinterpret_cast a template class to const version将模板类重新解释为 const 版本
【发布时间】:2021-07-12 02:13:34
【问题描述】:

AFAIK,带有模板参数<Type> 的模板类与<const Type> 完全不同。

template<typename T>
struct Wrapper
{
  T obj = T{};

  //other code 
};

现在我无法将Wrapper&lt;int&gt;&amp; 传递给需要Wrapper&lt;const int&gt;&amp; 的函数。

void someFunc(Wrapper<const int>& wrapper);
//...
Wrapper<int> wrapper;
someFunc(wrapper); //error

reinterpret_cast'ing 到它的 const 版本会出现什么问题?

operator Wrapper<const T>&() { return *(reinterpret_cast<Wrapper<const T>*>(this)); }

将上述行添加到Wrapper 使其无需创建新的&lt;const int&gt; 对象即可工作。 obj 不能在函数内部访问,所以传递的参数实际上是&lt;const Type&gt; 还是&lt;Type&gt; 应该没有关系。

如果没有模板专业化,这里有什么问题吗(就标准与实践而言)?

【问题讨论】:

    标签: c++ templates constants reinterpret-cast


    【解决方案1】:

    在 const 和非 const 情况下有许多不同的优化,这意味着类的内存布局(例如,因为 const 对象不需要实际存在)和类的用法都可以不同。

    换句话说:为此使用 reinterpret_cast 可能会导致意外行为,不应该这样做。

    在我看来,过度使用 const 关键字可能会导致更复杂的代码而没有任何收获,这就是其中之一。
    我建议避免&lt;const Type&gt; 的情况,而不是尝试处理它们。

    在不知道用例的情况下,在我看来,大多数用例都可以通过使用 const Wrapper&lt;T&gt; 而不是 Wrapper&lt;const T&gt; 来涵盖。

    【讨论】:

    • 谢谢! “类的内存布局和类的使用都可以不同”。你能为此提供任何参考吗?目前我将它用于一个“ID”类,就像一个对象的句柄。与指针 const ID&lt;T&gt;ID&lt;const T&gt; 类似,表示不同的东西。 (const float*float *const)对于资源管理器,如果资源是实际常量,那么我必须使用const_cast 来抛弃常量,除非我使用。如果我没记错的话。
    • @Newline:不需要或指定非 const 和 const 实例应该相同,所以我不能直接引用不存在的东西 ;-) 需要 reinterpret_cast因为没有这样的保证。如果您想深入了解优化只能影响 const 情况的兔子洞,我建议您研究“常量折叠”或其他有关如何处理 const 的问题(例如link
    • 我确实认为您的大多数问题是由于过度使用 const 关键字造成的。经验法则是,如果你需要抛弃 constness,它可能一开始就不应该是 const。在引用 const 或非 const 对象时,您的 ID 类是否需要以不同的方式工作?如果没有,我强烈建议始终使用模板的非常量版本(即ID&lt;int&gt;),而是使用const T 类型的成员变量,这在这两种情况下都应该有效。跨度>
    • 如果是const ID&lt;T&gt;那么我不能修改ID,如果是ID&lt;const T&gt;那么我不能修改它引用的对象。我希望它像一个指针,您可以在其中分别设置指针和指向对象的常量。如果指针是 int * ptr,那么没有 const-cast 就无法将它指向 const int
    • 好的,那么你有两种不同的类型,ID&lt;T&gt;ID&lt;const T&gt;,并且应该假设它们不同 - 即 reinterpret_cast 将导致未定义的行为。但是,我确实敦促您考虑所有这些 const 指定是否会对您的程序产生任何影响,或者它是否只会导致更复杂的代码来处理它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-28
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多