Не знаете типы параметров шаблона при приведении void * к шаблонному типу

#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
}