Рассмотрим следующий пример, минимальный пример:Тип стиранием и вид шаблонный метод
struct S {
using func_t = void(*)(void *);
template<typename T>
static void proto(void *ptr) {
static_cast<T*>(ptr)->f();
}
func_t func;
void *ptr;
};
struct T {
void f() {}
};
void g(S &s) {
s.func(s.ptr);
}
int main() {
T t;
S s;
s.func = &S::proto<T>;
s.ptr = &t;
g(s);
}
Довольно очевидно, идея заключается в том, чтобы удалить тип кучу объектов (как T
, что это не единственный доступный type), чтобы создать массив экземпляров S
, затем перебрать этот массив и вызвать заданную функцию-член.
Пока все хорошо, его легко реализовать, и оно работает.
Теперь я хотел бы, чтобы обеспечить внешнюю функцию, которая будет вызвана на стертого объекта, то, что будет так:
template<typename T, typename F>
static void proto(void *ptr, F &&f) {
auto *t = static_cast<T*>(ptr);
std::forward<F>(f)(*t);
t->f();
}
Или это:
template<typename T>
static void proto(void *ptr, void(*f)(T &)) {
auto *t = static_cast<T*>(ptr);
f(*t);
t->f();
}
Чтобы быть запущены:
s.func(s.ptr, [](auto obj){ /* ... */ });
Вид шаблона метода, в котором дополнительные функции предоставляются вызывающим, а не производным классом.
К сожалению, я не могу этого сделать, потому что не могу свести специализации к чему-то однородному, назначаемому указателю функции.
Единственной альтернативой я могу видеть, чтобы определить пользовательский класс как следующий:
struct C {
template<typename T>
void f(T &t) { /* ... */ }
// ...
};
Где f
депеши как-то вызов внутри функции правого члена, а затем использовать его как:
struct S {
using func_t = void(*)(void *, C &);
template<typename T>
static void proto(void *ptr, C &c) {
auto t = static_cast<T*>(ptr);
c.f(*t);
t->f();
}
func_t func;
void *ptr;
};
Это недалеко от того, что я сделал бы с помощью лямбда, но это более подробно и требует, чтобы я явно объявлял класс C
.
Есть ли другая подходящая альтернатива для достижения того же или это единственное жизнеспособное решение?
Я чувствую проблему [XY] (https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Можете ли вы дать нам код, который вы хотели бы написать, предполагая, что все поддерживающие магии шаблонов работают отлично? – nwp
@ nwp Я дал нечто подобное. Представьте себе, что у меня был стертый массив типа (допустим, я), я бы хотел, чтобы он повторял его, вызывая 's.func (s.ptr, [] (auto obj) {/ * ... * /});', каждый время с немного отличающимися лямбдами. Могу я дать вам более подробную информацию? Я не знаю, как это объяснить. Прости. – skypjack
Что общего между всеми элементами массива? У них просто есть общая функция-член 'void f()'? – nwp