2016-11-12 2 views
1

Обратите внимание на следующий код. Это шаблон функции, который работает с типом T в зависимости от его ширины бита. Фактический код более сложный, но это не имеет значения:Исключить часть шаблона функции во время компиляции

template <typename T> T MyFunc(T t) 
{ 
    constexpr const uint8_t typeBitCount = sizeof(T)*8; 

    // more code here that works fine for all widths 

    if (typeBitCount >= 32) 
    { 
     if (...) 
     { 
     return t >> 16; // warning right shift count >= width of type 
     } 

     if (typeBitCount >= 64) 
     { 
     if (...) 
     { 
      return t >> 32; // warning right shift count >= width of type 
     } 
     } 
    } 
} 

Я использую это также с 8-разрядными типами. В этом случае я получаю предупреждения (см. Прокомментированные строки). К сожалению, C++ не может оценить состояние if во время компиляции даже при использовании constexpr. Возможно, я мог бы подавить предупреждения, но это кажется мне взломанным. Я бы предпочел исключить проблемный код во время компиляции.

Как это можно решить (возможно, без нарушения кода на куски и без создания избыточности)?

Я использую GCC 5.4.0.

+0

Весь код должен быть скомпилирован. Выбор в зависимости от 'typeBitCount' происходит только во время выполнения, а не во время компиляции. Поэтому вы получаете предупреждения, когда компилятор приходит к этим строкам. –

+0

Это совершенно ясно. Вопрос в том, как решить эту проблему как можно чище. – Silicomancer

+0

Если у вас есть компилятор C++ 14, вы можете сделать всю функцию функцией 'constexpr' и оценить ее время компиляции (в зависимости от части« больше кода здесь ... »). Это может решить некоторые из ваших проблем. Или вы можете специализировать функцию для 8-битных типов и поместить общую часть «больше кода здесь ...» в отдельную функцию. –

ответ

0

Я, наконец, решил это без шаблонов. Вместо этого я использовал перегрузку. Я разбил код на куски и одну функцию для каждого типа, каскадные тезисы работают от 64-битной ширины до 8 бит.

1

Я бы вычислить проблемный сдвиг так, что:

  • , когда сдвиг должен быть выполнен, он имеет требуемое значение 32,
  • , если она не должна быть выполнена, она имеет некоторые небольшие значение 0:

    .... 
    constexpr uint8_t shift2 = (typeBitCount >= 64) ? 32 : 0; 
    .... 
    if (typeBitCount >= 64) 
        { 
        if (...) 
        { 
         return t >> shift2; 
        } 
        } 
    .... 
    
1

Вы можете использовать частичную специализацию шаблона аналогичной this answer для реализации функции в зависимости от типа размер с использованием функторов:

// Base implementation for unsupported size and type. 
template <typename T, size_t TSize> 
class MyFuncImpl; 

// 32-bit specialization. 
template <typename T> 
struct MyFuncImpl<T, 4> 
{ 
    T operator()(const T t) const 
    { 
     return t >> 16; 
    } 
}; 

// 64-bit specialization. 
template <typename T> 
struct MyFuncImpl<T, 8> 
{ 
    T operator()(const T t) const 
    { 
     return t >> 32; 
    } 
}; 

// Calling this functor will calculate the correct bit-shift at compile time and not emit warnings. 
template <typename T> 
T MyFunc(const T t) 
{ 
    return MyFuncImpl<T, sizeof(T)>()(t); 
} 

Вы также можете добавить дополнительные специализации для 8-битных и 16-разрядных типов. Вы бы использовали его следующим образом:

int main() 
{ 
    uint32_t test1 = 1235434; 
    std::cout << MyFunc(test1) << std::endl; 

    return 0; 
} 
Смежные вопросы