C++ 使用模板元编程计算整数中的设置位数时出现的问题

C++ 使用模板元编程计算整数中的设置位数时出现的问题,c++,C++,作为一个实验,我试图编写模板代码,在编译时计算整数中的集合位数。这是我的第一次尝试: template<unsigned long long x> struct BitCount { static const int result = (x == 0) ? 0 : ((x & 1) + BitCount<(x >> 1)>::result); }; ideone.com正确输出:2 1 2 0 Visual Studio 2013输出不正确:

作为一个实验,我试图编写模板代码,在编译时计算整数中的集合位数。这是我的第一次尝试:

template<unsigned long long x>
struct BitCount
{
    static const int result = (x == 0) ? 0 : ((x & 1) + BitCount<(x >> 1)>::result);
};
ideone.com正确输出:2 1 2 0

Visual Studio 2013输出不正确:1 12 0

这是VS中的一个bug还是我的代码中的某些内容不正确


谢谢

对于零的终止情况,需要专门化:

template<>
struct BitCount<0>
{
    static const int result = 0;
};
模板
结构位计数
{
静态常数int结果=0;
};

否则,您只需依赖主模板即可将
BitCount::result
定义为
true?0:BitCount::result
,这是一个无限递归的模板实例化。即使未对else子句求值,它仍需要实例化它。

您需要对终止为零的情况进行专门化:

template<>
struct BitCount<0>
{
    static const int result = 0;
};
模板
结构位计数
{
静态常数int结果=0;
};

否则,您只需依赖主模板即可将
BitCount::result
定义为
true?0:BitCount::result
,这是一个无限递归的模板实例化。它仍然需要实例化else子句,即使它没有被计算。

您可以使用以下命令:

template<unsigned long long x>
struct BitCount
{
    static constexpr const int result = (x & 1) + BitCount<(x >> 1)>::result;
};

template<>
struct BitCount<0>
{
    static constexpr const int result = 0;
};
顺便说一句,您可以使用位技巧
x&(x-1)
屏蔽最低设置位,而不是执行
x>>1
,如下所示:

constexpr int bitCount(unsigned long long x)
{
    return (x == 0) ? 0 : 1 + bitCount(x & (x - 1));
}

您可以使用以下选项:

template<unsigned long long x>
struct BitCount
{
    static constexpr const int result = (x & 1) + BitCount<(x >> 1)>::result;
};

template<>
struct BitCount<0>
{
    static constexpr const int result = 0;
};
顺便说一句,您可以使用位技巧
x&(x-1)
屏蔽最低设置位,而不是执行
x>>1
,如下所示:

constexpr int bitCount(unsigned long long x)
{
    return (x == 0) ? 0 : 1 + bitCount(x & (x - 1));
}

您需要专门处理基本情况,否则将得到无限编译时递归(基本情况的定义取决于基本情况的定义)。
此外,如果将初始化内联,效果会更好:

template<unsigned long long x>
struct PopCount
{
    static const int result = (x&1)+BitCount<(x>>1)>::result;
};
template<>
struct PopCount<0ULL>
{
    static const int result = 0;
}
作为最后一步,在运行时(C++14)执行函数时,使函数迭代以获得更好的性能


此赋值
x&=x-1清除最低顺序的集合位,因此所需的迭代次数更少。

您需要专门化基本情况,否则将得到无限编译时递归(基本情况的定义取决于基本情况的定义)。
此外,如果将初始化内联,效果会更好:

template<unsigned long long x>
struct PopCount
{
    static const int result = (x&1)+BitCount<(x>>1)>::result;
};
template<>
struct PopCount<0ULL>
{
    static const int result = 0;
}
作为最后一步,在运行时(C++14)执行函数时,使函数迭代以获得更好的性能


此赋值
x&=x-1
清除最低阶的集合位,因此需要的迭代次数更少。

无符号long long
无论其值如何,都具有相同的位数。@LightnessRacesinOrbit抱歉,将位设置为1这实际上作为
constexpr
函数会好得多。@NeilKirk:那你能纠正你的问题吗?谢谢。@LightnessRacesinOrbit我做了。
无符号长
无论其值如何,都有相同数量的位。@LightnessRacesinOrbit抱歉,位设置为1这实际上作为
constexpr
函数会好得多。@NeilKirk:那你能纠正你的问题吗?谢谢。@LightnessRacesinOrbit我看过。“顺便说一句”真的吗?4(00000100)和3(00000011)是0(00000000)。@LightnessRacesinOrbit:我可能不清楚,我的意思是函数可以重写如下:
return(x==0)?0:1+位计数(x&(x-1))而不是使用
x>>1
从4到2到1到0进行迭代。右键确定短语“删除最低设置位”使我感到厌烦,因为它没有讨论此替代实现中的其他不同之处。现在你有了代码就更清楚了,虽然一组示例和解释会让你更容易理解,这是一个更完整的答案?4(00000100)和3(00000011)是0(00000000)。@LightnessRacesinOrbit:我可能不清楚,我的意思是函数可以重写如下:
return(x==0)?0:1+位计数(x&(x-1))而不是使用
x>>1
从4到2到1到0进行迭代。右键确定短语“删除最低设置位”使我感到厌烦,因为它没有讨论此替代实现中的其他不同之处。现在你有了代码就更清楚了,尽管一组示例和解释会使它更容易理解,这是一个更完整的答案。