【问题标题】:How to make a template with customized bit shift values如何制作具有自定义位移值的模板
【发布时间】:2016-08-01 09:29:00
【问题描述】:

假设我需要一个函数模板,它对不同的整数类型执行不同的位移量。例如,如果输入值n 的类型为char,则该函数将对n>>2n<<3 进行一些计算。如果是short int,那么函数使用n>>1n<<8。对于int 类型,会有n>>11n<<9,以此类推。当然,上面提到的值只是举例,和int_type的大小没有关系。

我对这个问题的建议是这样的:

template <typename Num_Type = char, int s1 = 2, int s2 = 3> void test1(Num_Type &n)
{
    // this is just an example code:
    int a = n >> s1,
        b = n << s2;
    // do some calculations on a and b
}

所以我可以将此模板用于不同类型的输入值。但是当我编译它时,它给了我几个关于移位操作中未定义行为的警告,因为值可能太大了。

所以这个问题可以用两种形式提出:

  1. 如何自定义位移操作而不会收到“未定义行为”警告?或

  2. 我可以有一个有限的数据类型,比如intlength,它只能有一个指定的数字范围,比如0, 1, 2, ... , 31?我知道这听起来可能很愚蠢,但在这种情况下,我可以将模板定义为

    template <typename Num_Type = char, intlength s1 = 2, intlength s2 = 3> void test1(Num_Type &n)
    

因此编译器不应该抱怨移位值。

【问题讨论】:

  • 为什么会收到警告?我的意思是,你为什么要把n 换成太大的s1s2
  • @rozina 我不是想用太大的值来移动它,我的预期值很小,但是由于移动量是 int 类型,编译器认为它可能太大了
  • 我明白了。也许警告在这里没有用,您可以为此功能禁用它。为了安全起见,您可以将断言添加到函数体中,以测试 s1s2 不是太大。 Clang does not produce any warnings though
  • @rozina 你能提供更多细节吗?我在 C++ 方面不是很有经验,只依赖尝试和错误,当然还有 google
  • 我的问题的第二部分呢?

标签: c++ templates bit-manipulation undefined-behavior


【解决方案1】:

根据输入类型改变模板函数行为的健康方法是使用模板特化。例如:

template <typename num_t> test(num_t n);
template <> test<int> (num_t n){
    int shift_amount = 4;
    // do shifts
}
template <> test<char> (num_t n){
    int shift_amount = 1;
    // do shifts
}

此外,请确保使用 if 检查包围您的班次,以确保没有溢出。

【讨论】:

  • 这没什么区别
【解决方案2】:

我认为不需要模板。你所需要的只是简单的重载:

auto test(char n) { ... }
auto test(uint16_t n) { .. }
auto test(uint32_t n) { .. }

【讨论】:

  • 我知道。我的目标不是“解决”问题。我想知道怎么做
  • 而且如果代码非常大,函数重载会让人头疼
  • 那我不明白你的问题。我不明白你想要什么。
【解决方案3】:

您可以使用#pragma 命令禁用此功能的警告,具体取决于您使用的编译器。你必须自己用谷歌搜索。

编辑:因为你提到你正在使用 VisualStudio,here is a link to disable warnings. :)

禁用警告后,您可以添加static_assert 以检查s1s2 是否在Num_Type 的范围内。虽然我觉得奇怪的是你的编译器自己不这样做,因为一切都是在编译时知道的。

template <typename Num_Type, int s1 = 2, int s2 = 3> void test1(Num_Type &n)
{    
    constexpr auto max = sizeof(Num_Type) * 8;
    static_assert(s1 < max && s2 < max, "integer overflow");

    // this is just an example code:
    int a = n >> s1,
        b = n << s2;
}

Live demo

【讨论】:

    猜你喜欢
    • 2020-09-14
    • 2014-10-20
    • 2019-12-06
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    • 2016-03-09
    • 2016-12-23
    • 1970-01-01
    相关资源
    最近更新 更多