【问题标题】:Change only parts of a type in a C++ template仅更改 C++ 模板中类型的一部分
【发布时间】:2010-10-04 12:51:22
【问题描述】:

抛开目的和疯狂,有没有办法在 C++ 中实现这一点?

template <typename P>
void Q void_cast(P Q *p) const
{
    return static_cast<P Q *>(p);
}

我实际上是在尝试将指针转换为 void 指针类型,同时保留任何 const、restrict 和其他限定符(由 Q 表示)。

我的印象是 C++ 标准库(或者不太理想,在 Boost 中)中有一些东西可以让您“调整”类型的属性,其粒度比 const_cast 或 static_cast 更精细。

【问题讨论】:

  • 记住模板不仅仅是文本替换;一些模板参数 T 可以是 int[3] 并且函数参数 T &param 将是对数组的引用。

标签: c++ templates c++11 type-conversion


【解决方案1】:

所以,你想要const X* -> const void*、volatile X* -> volatile void* 等

您可以使用一组重载来做到这一点:

template<typename P>
void* void_cast(P* p)
{
    return p;
}

template<typename P>
void const* void_cast(P const* p)
{
    return p;
}

template<typename P>
void volatile* void_cast(P volatile* p)
{
    return p;
}

template<typename P>
void const volatile* void_cast(P const volatile* p)
{
    return p;
}

新的类型特征是 add_const、add_volatile、remove_const 和 remove_volatile。它们用于以已知方式转换一种类型的 cv 限定符,而不是将一种类型的 cv 限定符应用于另一种类型。

【讨论】:

  • 您已经准确地确定了我所追求的,并解释了类型特征与它的关系。我仍然希望有一种不那么冗长的方法来实现这一点。
  • @Matt:唯一不那么冗长的方法可能是根本不使用强制转换,因为您无法在单独的模板参数中捕获 cv 限定符。转换为适当限定的 void 指针是隐式发生的,只有 C-cast 可以删除限定符。
  • 最终,我认为这些不需要是模板。 void const* void_cast(void const* v) { return v; } 和朋友就够了,我相信。
  • 可能。模板需要一个指针,除非您指定指针类型(例如void_cast&lt;Y&gt;(x))或先将类型转换为指针(例如void_cast((Y*)x)),否则模板不能与可隐式转换为指针的类一起使用,而普通函数将接受到参数类型的隐式转换。
  • 在 C++ 中,T* 将隐式转换为 void*,但反之则不然。必须保留 cv 限定符,因此 const T* 将隐式转换为 const void*,但不会转换为 void*。
【解决方案2】:

在 boost 类型特征库中有一些删除限定符的工具

http://www.boost.org/doc/libs/1_44_0/libs/type_traits/doc/html/index.html

【讨论】:

    【解决方案3】:
    template<class From>
    typename copy_rpcv<void, From*>::type void_cast(From *p) {
      return p;  // implicit conversion works
    }
    

    带一点TMP utility:

    // "copy ref/pointer/const/volatile"
    template<class To, class From>
    struct copy_rpcv {
      typedef To type;
    };
    template<class To, class From> struct copy_rpcv<To, From&        > { typedef typename copy_rpcv<To, From>::type&         type; };
    template<class To, class From> struct copy_rpcv<To, From*        > { typedef typename copy_rpcv<To, From>::type*         type; };
    template<class To, class From> struct copy_rpcv<To, From const   > { typedef typename copy_rpcv<To, From>::type const    type; };
    template<class To, class From> struct copy_rpcv<To, From volatile> { typedef typename copy_rpcv<To, From>::type volatile type; };
    

    您必须为限制说明符添加另一种情况;它可能会工作得很好,但我不知道它作为 03 中的非标准功能(是在 0x 中吗?)如何交互:

    template<class To, class From> struct copy_rpcv<To, From* restrict> { typedef typename copy_rpcv<To, From>::type* restrict type; };
    

    我的解决方案与 Anthony's 的不同之处在于保留“嵌套”类型信息:

    int *const *const p = 0;
    void *const *const v = void_cast(p);
    

    【讨论】:

      猜你喜欢
      • 2011-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-10
      • 2016-03-31
      • 1970-01-01
      相关资源
      最近更新 更多