Также рассмотрите встроенные функции своих компиляторов.
На компиляторе GNU, например, можно просто использовать:
int __builtin_popcount (unsigned int x);
int __builtin_popcountll (unsigned long long x);
В худшем случае компилятор генерирует вызов к функции. В лучшем случае компилятор испустит инструкцию по CPU сделать то же задание быстрее.
GCC intrinsics даже работают через несколько платформ. Popcount станет господствующей тенденцией в x86 архитектуре, таким образом, будет иметь смысл начинать использовать внутреннее теперь. Другая архитектура имеет popcount в течение многих лет.
На x86, можно сказать компилятору, что это может предположить, что поддержка popcnt
инструкция с -mpopcnt
или -msse4.2
также включает векторные инструкции, которые были добавлены в том же поколении. См. опции . -march=nehalem
GCC x86 (или -march=
безотносительно ЦП, который Вы хотите, чтобы Ваш код принял, и настроиться для) мог быть хороший выбор. Выполнение получающегося двоичного файла на более старом ЦП приведет к отказу запрещенной команды.
Для создания двоичных файлов оптимизировал для машины, на которой Вы создаете их, используете -march=native
(с gcc, лязгом или ICC).
MSVC обеспечивает внутреннее для инструкции x86 popcnt
, но в отличие от gcc это - действительно внутреннее для аппаратной инструкции и требует поддержки оборудования.
Используя [1 111] вместо встроенного
В теории, любом компиляторе, который знает, как к popcount эффективно для целевого ЦП должен представить ту функциональность через C++ ISO std::bitset<>
. На практике Вы могли бы быть более обеспечены с разрядным взломом AND/shift/ADD в некоторых случаях для некоторых целевых центральных процессоров.
Для целевых архитектур, где аппаратные средства popcount являются дополнительным расширением (как x86), не, все компиляторы имеют std::bitset
, который использует в своих интересах его, когда доступно. Например, MSVC не имеет никакого способа включить popcnt
поддержка во время компиляции, и всегда использует поиск по таблице , даже с [1 115] (который подразумевает SSE4.2, хотя технически существует отдельный бит функции для [1 116].)
, Но по крайней мере Вы получаете что-то портативное, которое работает везде, и с gcc/clang с правильными целевыми опциями, Вы получаете аппаратные средства popcount для архитектуры, которая поддерживает его.
#include
#include
#include
template
//static inline // static if you want to compile with -mpopcnt in one compilation unit but not others
typename std::enable_if::value, unsigned >::type
popcount(T x)
{
static_assert(std::numeric_limits::radix == 2, "non-binary type");
// sizeof(x)*CHAR_BIT
constexpr int bitwidth = std::numeric_limits::digits + std::numeric_limits::is_signed;
// std::bitset constructor was only unsigned long before C++11. Beware if porting to C++03
static_assert(bitwidth <= std::numeric_limits::digits, "arg too wide for std::bitset() constructor");
typedef typename std::make_unsigned::type UT; // probably not needed, bitset width chops after sign-extension
std::bitset bs( static_cast(x) );
return bs.count();
}
См. asm от gcc, лязга, ICC и MSVC на проводнике компилятора Godbolt.
x86-64 gcc -O3 -std=gnu++11 -mpopcnt
испускает это:
unsigned test_short(short a) { return popcount(a); }
movzx eax, di # note zero-extension, not sign-extension
popcnt rax, rax
ret
unsigned test_int(int a) { return popcount(a); }
mov eax, edi
popcnt rax, rax
ret
unsigned test_u64(unsigned long long a) { return popcount(a); }
xor eax, eax # gcc avoids false dependencies for Intel CPUs
popcnt rax, rdi
ret
PowerPC64 gcc -O3 -std=gnu++11
испускает (для int
версия аргумента):
rldicl 3,3,0,32 # zero-extend from 32 to 64-bit
popcntd 3,3 # popcount
blr
Этот источник не является x86-конкретным или определенным для GNU вообще, но только компилирует хорошо для x86 с gcc/clang/icc.
Также примечание, что нейтрализация gcc для архитектуры без единственной инструкции popcount является byte-at-a-time поиском по таблице. Это не замечательно для ARM, например .
C # и CLR не поддерживают общие ограничения интерфейса, хотя вы можете ограничить его конкретным интерфейсом (см. Другие ответы). Боюсь, что самое близкое, что вы можете получить, это «класс» и проверить тип с помощью отражения во время выполнения. Зачем вообще вам нужно ограничение интерфейса?
Если вы спрашиваете о добавлении ограничения к определенному интерфейсу, это просто:
public void Register<T>( T data ) where T : ISomeInterface
Если вы спрашиваете, существует ли ключевое слово, например class или struct, чтобы ограничить диапазон возможных типов для T , это недоступно.
Хотя вы можете написать:
public void Register<T>( T data ) where T : class // (or struct)
вы не можете писать:
public void Register<T>( T data ) where T : interface
Это называется дословным строковым литералом в C #, и нужно просто поставить @ перед литералом. Это не только позволяет использовать несколько строк, но также отключает экранирование. Так, например, вы можете сделать:
string query = @"SELECT foo, bar
FROM table
WHERE name = 'a\b'";
Тем не менее, это включает в себя разрывы строк (используя любой разрыв строки в вашем источнике) в строку. Для SQL это не только безвредно, но, вероятно, улучшает читаемость везде, где вы видите строку - но в других местах это может не потребоваться, и в этом случае вам либо нужно не использовать многострочное дословное выражение. строковый литерал, с которого нужно начать, или удалите их из полученной строки.