Есть ли правильный способ использовать числовые значения в шаблонах? - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть ситуация, когда мне нужно разделить несколько блоков битов пополам. Есть ли способ объединить следующие две функции в нечто, напоминающее третью? Наличие чего-то вроде третьего кажется более правильным и общим.

pair<bitset<32>, bitset<32> > 
split_block_in_half(
  bitset<64> block
){
  bitset<block.size()> filter;
  for(size_t i = 0; i < filter.size()/2; ++i){
    filter.set(i);
  }

  return make_pair<bitset<block.size()/2>, bitset<block.size()/2> >(
    bitset<block.size()/2>(((block ^ (filter << (block.size()/2))) >> (block.size()/2)).to_ulong()),
    bitset<block.size()/2>((block ^ filter).to_ulong())
  );
}


pair<bitset<28>, bitset<28> > 
split_block_in_half(
  bitset<56> block
){
  bitset<block.size()> filter;
  for(size_t i = 0; i < filter.size()/2; ++i){
    filter.set(i);
  }

  return make_pair<bitset<block.size()/2>, bitset<block.size()/2> >(
bitset<block.size()/2>(((block ^ (filter << (block.size()/2))) >> (block.size()/2)).to_ulong()),
bitset<block.size()/2>((block ^ filter).to_ulong())
  );
}



template<
  typename N>
pair<bitset<N>, bitset<N> >
split_block_in_half(
  bitset<2*N> block
){
  bitset<block.size()> filter;
  for(size_t i = 0; i < filter.size()/2; ++i){
    filter.set(i);
  }

  return make_pair<bitset<block.size()/2>, bitset<block.size()/2> >(
    bitset<block.size()/2>(((block ^ (filter << (block.size()/2))) >> (block.size()/2)).to_ulong()),
    bitset<block.size()/2>((block ^ filter).to_ulong())
  );
}

Есть ли умный способ компиляции двух разных функций, описанных выше, или это не поддерживается?

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Вот полный рабочий пример, который не требует указания N.Я реализовал логику немного по-другому.Я предполагаю, что цель состоит в том, чтобы элемент first пары содержал биты старшего разряда, а second содержал биты младшего разряда.Имейте в виду, что ^ является логической операцией XOR , хотя она может напоминать логическое И, иногда используемое в логике высказываний.

template<size_t N>
pair<bitset<N/2>, bitset<N/2>> split_block_in_half(const bitset<N>& block){
    static_assert(N % 2 == 0 && N != 0, "N must be even and non-zero");
    pair<bitset<N/2>, bitset<N/2>> ret;
    for (size_t i = 0; i < N/2; ++i){
        ret.first[i] = block[i + N/2];
        ret.second[i] = block[i];
    }
    return ret;
}

int main() {

    bitset<64> bs { 0x1234567887654321 };

    auto halves = split_block_in_half(bs);

    std::cout << std::hex
        << halves.first.to_ullong() << '\n'
        << halves.second.to_ullong() << '\n';

    // prints:
    // > 12345678
    // > 87654321

    return 0;
}
0 голосов
/ 17 сентября 2018

Попробуйте целочисленное значение в параметре шаблона:

template <int N>
pair<bitset<N>, bitset<N>> 
split_block_in_half(
    bitset<2*N> block
)
......

Недостатком является то, что, поскольку 2*N не может быть выведено из вызовов функций, вам необходимо явно указать N:

split_block_in_half<28>(block); // where block is bitset<56>

Если вы определите это так, вы можете использовать SFINAE, чтобы ограничить, чтобы N было четным.

template <int N>
std::enable_if_t<
    N % 2 == 0,
    pair<bitset<N/2>, bitset<N/2>>
>
split_block_in_half(bitset<N>);

Если у вас нет C ++ 14, измените std::enable_if_t<> на typename std::enable_if<>::type (C ++ 11).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...