Можем ли мы создать оператор IF, который определяет, была ли переменная объявлена ​​как указатель в C / C ++ - PullRequest
2 голосов
/ 07 августа 2011

Предположим, что переменная pa всегда объявляется одним из двух способов:

double * pa

OR

doublepa

Можем ли мы создать оператор IF, который выполняет следующие операции:

IF (pa - указатель) {pa [0] = 1}

ELSE {pa = 1}

РЕДАКТИРОВАТЬ:

Пожалуйста, смотрите Как узнать, был ли заполнен массив указателей в C ++ / C для последующих действийвопрос

Ответы [ 3 ]

6 голосов
/ 07 августа 2011

Основы работы C ++ 0x std::is_pointer:

template <typename T>
struct is_pointer_helper {
    static const bool value = false;
};

template <template T>
struct is_pointer_helper<T*> {
    static const bool value = true;
};

Для этого примера нам не нужно использовать тип, поэтому нам нужно некоторое вычитание аргумента шаблона:

template <typename T>
bool is_pointer(const T &) {
    return is_pointer_helper<T>::value;
}

И все готово:

if (is_pointer(pa)) {
    pa[0] = 1;
} else {
    pa = 1;
}

НО, обратите внимание, что этот код по-прежнему не будет компилироваться, если только pa[0] = 1 и pa = 1 не являются допустимыми выражениями (и ни для одного из нихdouble и double* они оба действительны - если вы устанавливаете 0, то оба значения будут действительны для double*, но все равно только секунда для double).Поэтому, вероятно, вам нужен не явный тест «если», а перегруженная функция:

template <typename T>
void set_thingy(T &t) {
    t = 1;
}

template <typename T>
void set_thingy(T *pt) {
    set_thingy(*pt);
}

set_thingy(pa);

Или, поскольку pa всегда равен double или double*, нет необходимости фокусироваться натот факт, что один является указателем, а другой - нет, это просто два разных типа, к которым мы должны относиться по-разному.Поэтому нет необходимости в шаблонах:

void set_thingy(double &d) { d = 1; }
void set_thingy(double *p) { *p = 1; }

set_thingy(pa);
2 голосов
/ 07 августа 2011

Не напрямую, нет.Предположим, что есть способ сделать это, что-то вроде

if (__IS_POINTER(pa) {
    pa[0] = 1;
}
else {
    a = 1;
}

Что произойдет, если pa не является указателем?В вашей программе по-прежнему есть оператор pa[0] = 1;, и он недопустим, поэтому компилятор отклонит вашу программу.

В принципе вы можете выполнить тест во время компиляции:

#if __pa_IS_A_POINTER
pa[0] = 1;
#else
a = 1
#endif

но мощность препроцессора C ++ очень ограничена;у него нет возможности проверить тип переменной или выражения.

Если бы у вас была такая возможность, что бы вы с ней сделали?Скажите нам, какова ваша настоящая цель.

0 голосов
/ 07 августа 2011

В C ++ 0x вы можете использовать черты типа и decltype:

#include <type_traits>

if (std::is_pointer<decltype(x)>::value)
{
  /* ... */
}

В C ++ 98/03 у вас нет decltype, но теперь вам нужно будет объяснить, как вы могли бы иметь переменную, не зная ее типа. Если у вас есть его тип, вы можете использовать черту того же типа:

#include <tr1/type_traits>
template <typename T> void bogus(T x) // T could be a pointer or not
{
  if (std::tr1::is_pointer<T>::value) { /*...*/ }
}

Вы также можете просто определить свой собственный класс черт, если у вас нет или вы хотите использовать TR1:

template <typename> struct is_pointer { static const bool value = false; };
template <typename T> struct is_pointer<T*> { static const bool value = true; };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...