2016-11-12 70 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位类型。在这种情况下,我会收到警告(请参阅注释行)。不幸的是,即使使用constexpr,C++也无法在编译期间评估if条件。我大概可以压制这些警告,但这对我来说似乎很难受。我宁愿在编译时排除有问题的代码。

如何解决这个问题(可能不会破坏代码并且不会造成冗余)?

我正在使用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; 
}