Изменить только части типа в шаблоне C ++ - PullRequest
3 голосов
/ 04 октября 2010

Цель и безумие в стороне, есть ли способ достичь этого в 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.

Ответы [ 3 ]

7 голосов
/ 04 октября 2010

Итак, вы хотите 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-квалификаторов одного типа к другому.

1 голос
/ 06 октября 2010
template<class From>
typename copy_rpcv<void, From*>::type void_cast(From *p) {
  return p;  // implicit conversion works
}

С небольшой утилитой TMP :

// "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; };

Вы должны добавить еще один случай для спецификатора restrict; это, вероятно, будет работать просто отлично, но я не знаю, как это, как нестандартная функция в 03 (это в 0x?), взаимодействует:

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

Мое решение отличается от Энтони в сохранении информации «вложенного» типа:

int *const *const p = 0;
void *const *const v = void_cast(p);
1 голос
/ 04 октября 2010

В lib черт типа надстройки есть некоторые инструменты для удаления Qulifiers

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

...