Как поместить интерфейсное ограничение на общий метод в C# 3.5?

Также рассмотрите встроенные функции своих компиляторов.

На компиляторе 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, например .

6
задан Maniero 23 January 2015 в 03:37
поделиться

3 ответа

C # и CLR не поддерживают общие ограничения интерфейса, хотя вы можете ограничить его конкретным интерфейсом (см. Другие ответы). Боюсь, что самое близкое, что вы можете получить, это «класс» и проверить тип с помощью отражения во время выполнения. Зачем вообще вам нужно ограничение интерфейса?

4
ответ дан 8 December 2019 в 16:08
поделиться

Если вы спрашиваете о добавлении ограничения к определенному интерфейсу, это просто:

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
11
ответ дан 8 December 2019 в 16:08
поделиться

Это называется дословным строковым литералом в C #, и нужно просто поставить @ перед литералом. Это не только позволяет использовать несколько строк, но также отключает экранирование. Так, например, вы можете сделать:

string query = @"SELECT foo, bar
FROM table
WHERE name = 'a\b'";

Тем не менее, это включает в себя разрывы строк (используя любой разрыв строки в вашем источнике) в строку. Для SQL это не только безвредно, но, вероятно, улучшает читаемость везде, где вы видите строку - но в других местах это может не потребоваться, и в этом случае вам либо нужно не использовать многострочное дословное выражение. строковый литерал, с которого нужно начать, или удалите их из полученной строки.

0
ответ дан 8 December 2019 в 16:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: