Странно #define в шаблоне? - PullRequest
       20

Странно #define в шаблоне?

0 голосов
/ 15 сентября 2010

Я получил небольшой кусочек кода из библиотеки, который делает это:

#define VMMLIB_ALIGN( var ) var

template< size_t M, typename T = float >
class vector
{

...

private:
// storage
VMMLIB_ALIGN( T array[ M ] );

};

И вы можете позвонить, выполнив

//(vector<float> myVector)
myVector.array;

Никаких скобок или чего-то еще.

что?


Прочитав ответы, похоже, мне следовало больше поискать. «Переход к определению» XCode дал мне только один результат. Поиск в библиотеке дал мне другое:

#ifndef VMMLIB_CUSTOM_CONFIG
#  ifndef NDEBUG
#    define VMMLIB_SAFE_ACCESSORS
#  endif
#  define VMMLIB_THROW_EXCEPTIONS
#  ifdef VMMLIB_DONT_FORCE_ALIGNMENT
#    define VMMLIB_ALIGN( var ) var
#  else
#    ifdef __GNUC__
#      define VMMLIB_ALIGN( var ) var __attribute__((aligned(16)))
#    elif defined WIN32
#      define VMMLIB_ALIGN( var ) __declspec (align (16)) var
#    else
#      error "Alignment macro undefined"
#    endif
#  endif
#endif

Это предлагает различные настройки, в зависимости от того, для какой системы он собирается.

Независимо, спасибо. Не могу поверить, что я запутался из-за доступа пользователя!

Ответы [ 4 ]

4 голосов
/ 15 сентября 2010

В конечном счете, myVector.array относится к переменной массива в классе, и переменные не нуждаются в обозначении вызова функции ().

BTW / все заглавные идентификаторы должны использоваться только для макросов препроцессора (как они здесь). В этом случае необходимо использовать макрос VMMLIB_ALIGN, чтобы упростить последующее «расширение» кода, сгенерированного для переменной array и рядом с ней (например, добавив к ней префикс static, extern, const, volatile или что-то специфичное для компилятора ) и / или добавление некоторых связанных функций, таких как функции get / set / search / clear / serialise, которые работают с массивом.

В общем - когда вы не уверены в том, что делает макрос, вы можете лучше понять, запустив компилятор с ключом командной строки, запрашивающим вывод препроцессора (в GNU g ++ этот переключатель равен -E) .. ... тогда вы сможете увидеть фактический исходный код, с которым правильно работает компилятор C ++.

РЕДАКТИРОВАТЬ - мало комментариев по поводу вашего комментария, но слишком долго, чтобы включать в мой собственный комментарий ...

Классы C ++ являются закрытыми, пока не будет предоставлен другой спецификатор доступа (но на практике общедоступный интерфейс - обычно ставится на первое место, поэтому программист все равно должен помнить об использовании private). структуры являются общедоступными по умолчанию. Таким образом, данные эффективно отображаются по умолчанию в наиболее распространенном стиле кодирования. И ему не нужна семантика функциональных вызовов для доступа к ней. Objective-C может быть лучше в этом ... ваш комментарий подразумевает, что вы используете функциональную запись вызовов для членов данных и функций, которая по умолчанию скрыта? Это так хорошо иметь общие обозначения! В C ++ сложный случай, когда у вас есть что-то вроде ...

struct Point
{
    double x, y;
};

...

// client usage:
this_point.x += 3 - that_point.y;

... затем хотите изменить на ...

struct Point
{
    double angle, distance;
};

... вам понадобятся довольно причудливые и подробные, закодированные вручную и не очень эффективные прокси-объекты x и y, чтобы старый клиентский код оставался неизменным, вычисляя x и y на лету, а также обновляя угол и расстояние по мере необходимости. Унифицированная нотация замечательна - она ​​позволяет варьировать реализацию без изменений исходного кода клиента (хотя клиенты должны будут перекомпилировать).

3 голосов
/ 15 сентября 2010

возможно я слишком упрощаю, но если вы посмотрите на макрос #define, он просто записывает переменную в класс.

Итак, у вас есть

class vector
{
...
  T array[ M ];
};

после расширения. Так что это просто публичная переменная в вашем классе.

1 голос
/ 16 сентября 2010

Во-первых, для записи, шаблоны не имеют к этому никакого отношения. Не существует особого взаимодействия между макросом и тем фактом, что ваш класс является шаблоном.

Во-вторых, исходя из имени макроса, я предполагаю, что он предназначен для выравнивания переменной.

То есть, чтобы получить выровненный экземпляр x типа X, вы должны использовать VMMLIB_ALIGN(X x);

На практике макрос вообще ничего не делает. Он просто вставляет свой аргумент, поэтому приведенный выше код приводит к коду X x; и ничего больше.

Однако может случиться так, что макрос определяется по-разному в зависимости от аппаратной платформы (поскольку требования к выравниванию могут различаться для разных платформ) или со временем (используйте реализацию фиктивного заполнителя, подобную этой, и затем замените ее на " реальная "реализация позже)

Однако это кажется бессмысленным, поскольку компилятор уже обеспечивает естественное выравнивание для всех переменных.

1 голос
/ 15 сентября 2010

array - это не метод, это массив типа T размера M.

...