Как использовать подкласс шаблона класса для вывода параметров шаблона функции шаблона в C ++? - PullRequest
1 голос
/ 01 марта 2012

Это может быть очень глупо ...

Если у меня есть такой шаблон класса А,

template <class T1, class T2>
struct A
{
    T1 a;
    T2 b;
};

и функция работает на нем,

template <class T1, class T2>
void foo(A<T1, T2> *p)
{
}

теперь я подкласс A,

struct B : A<int, int>
{
};

B b[100];

Не могу вывести параметр шаблона ...

foo(b);

и я должен написать так,

foo((B *)b);

или как это,

foo<int, int>(b);

а теперь еще кое-что, Я хотел бы, чтобы foo мог принять что-то T кроме A и рассматривать их как A

template <class T>
struct A<T, void>
{
    T a;
};

template <class T>
void foo(T *p)
{
    foo((A<T, void> *)p);
}

теперь, если я не напишу так, более поздний foo называется ...

foo<int, int>(b);
  1. Как можно упростить вывод параметров шаблона из массива подкласса?
  2. Как сделать так, чтобы подкласс имел более высокий приоритет, чем другой класс, при поиске перегруженной функции?

Это, кажется, подойдет

template <class T>
struct is_A_derived
{
    typedef char (&yes)[1];
    typedef char (&no)[2];

    template <class T1, class T2>
    static yes test(A<T1, T2> *);
    static no test(...);

    template <class T1, class T2>
    static A<T1, T2> get_type(A<T1, T2> *);
    static A<T, void> get_type(...);

    template <class T1, class T2>
    static A<T1, T2> base_type(A<T1, T2> *);
    static int base_type(...); // guess or maybe hope this "int" is never used

    static const bool value = sizeof(test((T *)0)) == sizeof(yes);
    static const bool identical = value && sizeof(base_type((T *)0)) == sizeof(T);

    typedef typename std::conditional<identical, decltype(get_type((T *)0)), A<T, void>>::type type;
};

Ответы [ 2 ]

1 голос
/ 01 марта 2012

Просто имейте в виду, что этот код потерпит неудачу . Вы не можете использовать массивы в стиле C полиморфно (независимо от шаблонов).

То есть вы не можете обрабатывать массив 100 * как массив 100 * 1006.

Как вы думаете, что произойдет, если вы напишите p[1]? Что ж, внутри происходит следующее:

*(p + 1)

Указатель арифметики. Теперь + 1 далее переводится компилятором в приращение на sizeof A байтов. Но ваша структура данных не большая sizeof A, а sizeof B! Так что p[1] будет указывать на неправильное место в памяти.

Таким образом, компилятор (совершенно случайно!) Правильно делает, запрещая этот вызов.

0 голосов
/ 01 марта 2012

В первом случае на самом деле существует опасность затухания массива B до указателя A *, если вам случится сделать арифметику с указателем на указателе A *.не разрешает, но может быть хорошей функцией безопасности, на случай, если вы планируете выполнить функцию над массивом A, которая не будет работать с массивом B.

Вы можете сделать foo( &b[0] ) вместо приведения или явных шаблонов.

В последнем случае вы теперь усложняете функцию функцией foo на вашем T *, если она имеет то же имя, что и функция в шаблоне A.

После добавления второго foo, вызов на B действительно выберет второй foo, потому что теперь он становится идеальным совпадением.Подклассу может быть дан более высокий приоритет с помощью умных техник SFINAE, чтобы увидеть, является ли он А или нет.В общем, хотя я бы избегал использовать это, если вам действительно не нужно.

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