#c #templates #generics
#c #шаблоны #общие сведения
Вопрос:
Я использую библиотеку pthreads, и когда я создаю поток, я даю ему указатель на объект шаблонного типа.
У меня нет опыта работы с шаблонами (только что прочитал о них сегодня), и мне нужно привести параметр void * из объявления метода, который запускает pthread, к шаблонному типу, чтобы я мог получить доступ к его элементам. Короче говоря, что-то, что выглядит так:
Короче говоря, что-то вроде этого:
template <typename T>
class A {
...
...
...
void aMember() { ... }
};
int main() {
A<int> a;
pthread_create(..., ..., amp;run, amp;a);
...
...
...
}
void *run(void *arg) {
(A*)arg->aMember()
}
Моя проблема в том, что я получаю все эти ошибки, которые я не знаю, как исправить. На самом деле я понимаю ошибки, но не знаю решения. Вот ошибки:
ошибка: ожидаемое первичное выражение перед (ошибка токена: отсутствуют аргументы шаблона перед * ошибка токена: ожидаемое первичное выражение перед) ошибка токена: ожидаемое `)’ перед ‘info’
Я просто не понимаю, как я мог когда-либо узнать типы аргументов A, когда я применяю к нему один раз в потоке?
Я использую C Templates: The Complete Guide book в качестве справочного / учебного ресурса и должен сказать, что я переполнен всей информацией, необходимой для полного понимания шаблонов. Мне было интересно, есть ли у кого-нибудь решение проблемы или он мог бы указать мне направление другого ресурса, который мог бы предоставить ответы.
Как всегда, я очень ценю вашу помощь.
РЕДАКТИРОВАТЬ / ОБНОВЛЯТЬ
Кажется, что добавление контекста к моей проблеме могло бы помочь. В качестве альтернативы, возможно, кто-то может предоставить другое решение, используя другой дизайн.
Я использую libcurl для выполнения HTTP-запросов и в зависимости от полученного ответа создам объект определенного типа (таким образом, шаблоны). Я создаю новый поток для каждого запроса, который я хотел бы выполнить, чтобы все выполнялось асинхронно.
Комментарии:
1. Извините. Я должен был добавить контекст к моей проблеме ранее, но я использую библиотеку pthreads.
Ответ №1:
template<typename T>
void *run(void *arg) {
static_cast<A<T>*>(arg)->aMember();
}
int main() {
A<int> a;
pthread_create(..., ..., amp;run<int>, amp;a);
...
...
...
}
Это, как и ваш исходный фрагмент кода, зависит от соглашения о вызовах extern «C «, которое совпадает с тем, что использует ваша библиотека pthread. Я не уверен, есть ли у POSIX какие-либо требования, чтобы они были одинаковыми, но если они отличаются, вам не повезло, потому что вы не можете предоставить шаблонам функций привязку к языку C.
Комментарии:
1. Я думаю, что я сталкиваюсь с проблемой привязки, о которой вы упомянули, поскольку в pthread_create указано неопределенная ссылка на void* MyClass::run<std::basic_string<…..>>(void *), когда я, очевидно, вызываю run, используя <std::string>
2. @Chris когда вы говорите,
amp;run<std::string>
вам нужно иметь определениеrun
в области видимости.3. Потрясающе, жаль, что я не нашел эту тему, когда столкнулся с такой же проблемой при приведении типов для объектов в помощниках функций pthread. Но один вопрос: можете ли вы передавать шаблоны в pthread_create?
Ответ №2:
Шаблоны классов не являются классами, они генерируют классы при задании аргументов шаблона. Аналогично, вы не можете приготовить печенье из формочки для печенья, пока не предоставите тесто для печенья. Приведение к A
бессмысленно.
Трудно сказать, каково правильное решение, поскольку вы не сказали, чего вы пытаетесь достичь, только шаг, который вы предпринимаете. Если run
следует работать только с одним типом, вы знаете, что аргумент шаблона всегда будет одним и тем же; вы могли бы сделать это:
void *run(void *arg) {
A<int>* a = static_cast<A<int>*>(arg);
a->aMember();
}
Если run
можно работать с разными A
экземплярами и не нужно беспокоиться о других, run
сам может быть шаблоном:
template <typename T>
void *run(void *arg) {
A<T>* a = static_cast<A<T>*>(arg);
a->aMember();
}
pthread_create(..., ..., amp;run<int>, amp;a);
Если run
необходимо единообразно работать с любым типом, это невозможно. Однако вы можете исключить общий интерфейс, не зависящий от типа, и обратиться к базе, не являющейся шаблоном:
class ABase {
public:
// functionality present regardless of template argument
virtual void aMember() = 0;
// polymorphic bases should always have virtual destructors
virtual ~ABase() {}
};
template <typename T>
class A : public ABase {
public:
void aMember() { /* use type information */ }
};
void *run(void *arg) {
ABase* a = static_cast<ABase*>(arg);
a->aMember(); // dynamic dispatch
}