2013-04-04 2 views
2

Я возвращаюсь на C++ (или хорошо, технически, Objective-C++) после многих лет отсутствия, поэтому, пожалуйста, несите меня. Я пытаюсь использовать шаблоны для реализации решения, которое в противном случае потребовало бы тонны кода вырезания и вставки. Отрывок ниже показывает основную суть усилий:Почему оператор этого функтора() нуждается в модификаторе trailing const?

namespace { 

    using vMAT::DOUBLE; 
    using vMAT::SINGLE; 
    using vMAT::INT8; 
    using vMAT::UINT8; 
    using vMAT::INT16; 
    using vMAT::UINT16; 
    using vMAT::INT32; 
    using vMAT::UINT32; 
    using vMAT::INT64; 
    using vMAT::UINT64; 

    typedef void (* swapFn)(void * vector, vDSP_Length vectorLength); 

    // Functor used for template arguments. 
    template <typename TypeA> 
    struct swapbytes { 
     swapFn fn; 

     swapbytes() 
     { 
      if  (sizeof(TypeA) == 8) fn = vMAT_byteswap64; 
      else if (sizeof(TypeA) == 4) fn = vMAT_byteswap32; 
      else if (sizeof(TypeA) == 2) fn = vMAT_byteswap16; 
      else if (sizeof(TypeA) == 1) fn = NULL; 
      else NSCAssert(NO, @"Oops!"); 
     } 

     void operator()(void * vector, vDSP_Length vectorLength) const 
     // ..................................................... ^^^^^ Why? 
     { 
      if (fn != NULL) fn(vector, vectorLength); 
     } 
    }; 

    template <typename TypeA, typename ClassB> 
    void 
    loadFromOperation(vMAT_MATv5NumericArray * self, 
         vMAT_MATv5ReadOperation * operation, 
         TypeA a, 
         ClassB b) 
    { 
     swapbytes<TypeA> SwapA; 
     long lenC = self.size[0] * sizeof(TypeA); 
     TypeA * C = (TypeA *)malloc(lenC); 
     long lenD = vMAT_Size_prod(self.size) * sizeof(ClassB); 
     self.arrayData = [NSMutableData dataWithCapacity:lenD]; 
     self.arrayData.length = lenD; 
     ClassB * D = (ClassB *)[self.arrayData mutableBytes]; 
     __block long idxD = 0; 
     vMAT_Size123Iterator(self.size, ^(int32_t n, int32_t o, int32_t p) { 
      [operation readComplete:C 
          length:lenC]; 
      if (operation.swapBytes) { SwapA((void *)C, lenC/sizeof(TypeA)); } 
      for (int m = 0; 
       m < self.size[0]; 
       m++) { 
       D[idxD] = C[m]; 
       ++idxD; 
      } 
     }); 
     free(C); 
    } 

} 

- (void)_load_miUINT8_mxDOUBLE_fromOperation:(vMAT_MATv5ReadOperation *)operation; 
{ 
    loadFromOperation(self, operation, UINT8, DOUBLE); 
} 

Мой вопрос, как я надеюсь, что видно из комментария, заканчивая «Почему?», Вот почему это const декларация необходима здесь? Если он отклоняется, компилятор жалуется, что нет сигнатуры метода, соответствующей месту вызова, по адресу SwapA(...) в теле loadFromOperation.

Я бы это понял, если SwapA были явно объявлены как const, но это не так. Очевидно, что может быть be, так как его работа не зависит от изменения какого-либо состояния, но это не относится к точке.

И в то время как у меня есть другая полезная пара глаз на этот код, я бы приветствовать любой стиль или другие критические замечания более опытный C++ практикующий может заботиться, чтобы предложить ...

+1

Что это за синтаксис '^ (...) {...}'? Некоторое расширение лямбда? Ой, подождите, это Objective-C++? –

+0

Да: расширение Blocks присутствует в компиляторах LLVM и GCC от Apple. Извините, я забыл, что здесь есть блок. –

ответ

3

Непро- __block переменные, которые фиксируются с помощью блока , копируются в блок по значению при создании блока и составляют const внутри блока. то есть внутри блока, SwapA имеет тип const swapbytes<TypeA>.

+0

Huzzah! Это объясняет это, спасибо! Я начал думать, что в компиляторе должна быть какая-то непонятная ошибка ... Я полностью игнорировал, как C++ может взаимодействовать с расширением Blocks. –