Проблема с указателями на методы и шаблоны, C ++ - PullRequest
0 голосов
/ 12 февраля 2011

Существует 2 класса шаблонов A и B, имеющих 2 закрытых члена a1, a2 и b1, b2.

template <typename T>
class A
{
private:
    T a1, a2;

public:
    T getA1 () const {return a1;}
    T getA2 () const {return a2;}

};


template <typename T>
class B
{
private:
    T b1, b2;

public:
    T getB1 () const {return b1;}
    T getB2 () const {return b2;}

};

В классе Test требуется 2 указателя, указывающих на получатели.

class Test
{
  private:
    template <typename T>
    static T ( *getFirst ) ();

    template <typename T>
    static T ( *getSecond ) ();

}


template <typename T>
T ( * Test::getFirst ) ()  =  &A<T>::getA1; //Pointer to getA1, error

template <typename T>
T ( * Test::getSecond ) ()  =  &B<T>::getB2; //Pointer to getB2, error

int main
{
   A <double> a;
   B <double> b;

   double c = a.getFirst + b.getSecond;
}

T представляет фундаментальные типы данных ... Возможно ли реализовать этот код без специализации (например, указатели на члены шаблона класса) или эти "указатели" должны быть специализированными?Спасибо за любые примеры ...

Ответы [ 4 ]

0 голосов
/ 12 февраля 2011

Ваш код кажется довольно запутанным, поэтому я не уверен, что действительно понял, о чем вы просите ... вот адаптация вашего примера, который компилируется.

// This is one template class A with two getters
template <typename T>
class A
{
private:
    T a1, a2;

public:
    T getA1 () const {return a1;}
    T getA2 () const {return a2;}
};

// This is another unrelated template class, with two other getters
template <typename T>
class B
{
private:
    T b1, b2;

public:
    T getB1 () const {return b1;}
    T getB2 () const {return b2;}
};

// These are declarations of generic "getFirst" and "getSecond"
template<typename T1, typename T2>
T1 getFirst(const T2& t);

template<class T1, class T2>
T1 getSecond(const T2& t);

// Here I'm specializing getFirst/getSecond for the A template
template<class X>
double getFirst(const A<X>& a)  { return a.getA1(); }

template<class X>
double getSecond(const A<X>& a) { return a.getA2(); }

// Here I'm doing the same for the B template
template<class X>
double getFirst(const B<X>& b)  { return b.getB1(); }

template<class X>
double getSecond(const B<X>& b) { return b.getB2(); }

// Now I can use getFirst/getSecond with either A or B
int main(int argc, const char *argv[])
{
   A<double> a;
   B<double> b;
   double c = getFirst(a) + getSecond(b);
   return 0;
}
0 голосов
/ 12 февраля 2011

Короче, это невозможно.

Во-первых, вы не можете объявить указатель на функцию шаблона, только указатель на конкретную функцию. Во-вторых, вы пытались объявить указатель на свободную функцию, но A::getA1 является функцией-членом с неявным аргументом this, поэтому семантика не совпадает.

Вы можете сделать что-то вроде этого:

template <typename T>
struct A
{
    static T get() { return T() };
};

template <typename T>
struct Holder
{
    typedef T(A<T>::*F_ptr)();
    static F_ptr f_ptr;
};


template <typename T>
typename Holder<T>::F_ptr Holder<T>::f_ptr  =  &A<T>::get;

сохранить указатель на функцию шаблона в качестве члена класса шаблона

0 голосов
/ 12 февраля 2011

Строка:

template <typename T>
T (*Test::getFirst)() = &A<T>::getA1; //Pointer to getA1, error

Имеет две проблемы: Первая состоит в том, что &A<T>::getA1 имеет тип T (A::*)()const, но getFirst имеет тип T (*)().Они несовместимы, поскольку первый является указателем на функцию-член, а второй - нет.

Вторая проблема со строкой заключается в том, что созданные объекты будут отличаться только по типу возвращаемого значения.Точно так же, как вы не можете вручную объявить как double (A::*getFirst)()const, так и char (A::*getFirst)()const, вы также не можете создать шаблон, который бы автоматически объявил оба из них.

Строка:

double c = a.getFirst + b.getSecond;

Имеет свой собственный набор проблем, которые могут или не могут быть связаны с рассматриваемой проблемой.

Извините за этот "не ответ".возможно, если вы поговорили больше о том, что вы пытаетесь достичь, а не о том, как вы пытаетесь это сделать, мы сможем помочь.

0 голосов
/ 12 февраля 2011

Вы делаете незаконные вещи.Смотрите,

template <typename T>
static T ( *getFirst ) ();

Здесь вы пытаетесь определить указатель на шаблонную функцию , что недопустимо в C ++.

Стандарт C ++ говорит в $ 14/1,

Шаблон определяет семейство классов или функций .

Обратите внимание, что он не скажем "шаблон определяет семейство классов , функций или указателей на функции ".Итак, вы пытаетесь определить «семейство указателей функций» с использованием шаблона, что недопустимо.


Если вам нужен указатель на функцию, вы можете сделать что-то вроде этого,

template <class T>
struct A
{
   static T (*FunctionPointer)(); //function pointer
};

struct B
{
   template <class T>
   static T Function(); //static function, not function pointer
};

int (*A<double>::FunctionPointer)() = &B::Function<double>;

Еще лучше: используйте объект функции .: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...