Цитата из документации о тяге :
Обобщение состоит в том, что если элемент появляется m раз в [keys_first1, keys_last1) и n раз в [keys_first2, keys_last2 ) (где m может быть нулем), то в диапазоне выходных данных клавиш появляется min (m, n) раз
blockquote>. Поскольку
comp
содержит только один ключ один раз,n=1
и поэтомуmin(m,1) = 1
.Чтобы получить «все валы, где соответствующий ключ содержится в comp», вы можете использовать подход моего ответа на аналогичную проблему .
Аналогично, код примера выполняет следующие шаги:
- Получить наибольший элемент из
d_comp
. Это предполагает, чтоd_comp
уже отсортирован.- Создайте вектор
d_map
размераlargest_element+1
. Скопируйте1
во все позиции записейd_comp
вd_map
.- Скопируйте все записи из
d_vals
, для которых есть запись1
вd_map
наd_result
,#include
#include #include #include #include #include #include #define PRINTER(name) print(#name, (name)) void print(const char* name, const thrust::device_vector & v) { std::cout << name << ":\t"; thrust::copy(v.begin(), v.end(), std::ostream_iterator (std::cout, "\t")); std::cout << std::endl; } int main() { int keys[] = {1, 1, 1, 3, 4, 5, 5}; int vals[] = {1, 2, 3, 4, 5, 6, 7}; int comp[] = {1, 5}; const int size_data = sizeof(keys)/sizeof(keys[0]); const int size_comp = sizeof(comp)/sizeof(comp[0]); // copy data to GPU thrust::device_vector d_keys (keys, keys+size_data); thrust::device_vector d_vals (vals, vals+size_data); thrust::device_vector d_comp (comp, comp+size_comp); PRINTER(d_keys); PRINTER(d_vals); PRINTER(d_comp); int largest_element = d_comp.back(); thrust::device_vector d_map(largest_element+1); thrust::constant_iterator one(1); thrust::scatter(one, one+size_comp, d_comp.begin(), d_map.begin()); PRINTER(d_map); thrust::device_vector d_result(size_data); using namespace thrust::placeholders; int final_size = thrust::copy_if(d_vals.begin(), d_vals.end(), thrust::make_permutation_iterator(d_map.begin(), d_keys.begin()), d_result.begin(), _1 ) - d_result.begin(); d_result.resize(final_size); PRINTER(d_result); return 0; } выход:
d_keys: 1 1 1 3 4 5 5 d_vals: 1 2 3 4 5 6 7 d_comp: 1 5 d_map: 0 1 0 0 0 1 d_result: 1 2 3 6 7
Можно легко наследоваться тому классу:
class Derived: public TimerEvent {
...
};
Однако Вы не можете переопределить HandleTimer в своем подклассе и ожидать, что это будет работать:
TimerEvent *e = new Derived();
e->HandleTimer();
Это вызвано тем, что статические методы не имеют записи в vtable, и не могут таким образом быть виртуальными. Можно однако использовать "пустой* Аргумент" для передачи указателя на экземпляр... что-то как:
struct TimerEvent {
virtual void handle(int fd, short event) = 0;
static void HandleTimer(int fd, short event, void *arg) {
((TimerEvent *) arg)->handle(fd, event);
}
};
class Derived: public TimerEvent {
virtual void handle(int fd, short event) {
// whatever
}
};
Таким образом, HandleTimer может все еще использоваться от функций C, просто удостоверьтесь, что всегда передали "реальный" объект как "пустой* Аргумент"
У Вас есть определенный конфликт здесь в Вашем вопросе. Когда Вы передаете &TimerEvent::TimerHandler
библиотеке C, Вы делаете точно это. Вы, возможно, также передали &DerivedTimerEvent::TimerHandler
, если Вы хотели. Но Вы не можете передать &TimerEvent::TimerHandler
и ожидать библиотека C (!) выяснять, что Вы на самом деле имели в виду &DerivedTimerEvent::TimerHandler
.