非模板参数在模板递归中缩小

时间:2016-07-07 09:31:23

标签: c++ templates c++11

我有以下代码,它应该在编译时计算字节中的位数。

template<unsigned char c, size_t I>
struct char_bit
{
    static constexpr size_t get() noexcept {
        return c > 0 ? char_bit<c << 1, I + 1>::get() : I
    }
};

int main()
{   
    std::cout << char_bit<1, 0>::get();
}

通过将1传递给unsigned char参数,我期望得到8的最终结果,因为它将向左移动8次,直到char变为0。

但是,使用Clang 3.7.1进行编译时,出现了编译错误:

  

错误:非类型模板参数的计算结果为256,但不能   缩小为'unsigned char'[-Wc ++ 11-narrowing]

为什么会这样?我该如何解决?

4 个答案:

答案 0 :(得分:3)

避免此错误的一种方法是反过来:不是溢出你的char,而是从最大和右移开始直到你达到零。你需要一个专门化来使代码工作(无论如何你都需要它):

#include <iostream>
using namespace std;

template<unsigned char c, size_t I>
struct char_bit
{
    static constexpr size_t get() noexcept {
        return char_bit< (c >> 1), I + 1>::get();
    }
};

template<size_t I>
struct char_bit<0, I>
{
    static constexpr size_t get() noexcept {
        return I;
    }
};


int main()
{   
    constexpr unsigned char c = static_cast<unsigned char>(-1);
    std::cout << char_bit<c, 0>::get();
}

答案 1 :(得分:2)

已有一个标准宏:

#include <climits>

int main() {
    std:cout << CHAR_BIT << std::endl;
}

答案 2 :(得分:1)

OP说这是有效的,所以我将其作为答案发布:

char_bit<(unsigned char)(c << 1), I + 1>::get()

答案 3 :(得分:0)

我不确定为什么会这样。但我认为,您可以使用模板功能专业化来修复它。

template<unsigned char c, size_t I>
struct char_bit
{
    static constexpr size_t get() noexcept {
        return char_bit<(c << 1), I + 1>::get();
    }
};

template <size_t I>
struct char_bit<0, I>
{
    static constexpr size_t get() noexcept { return I; }
};