Симметричные аргументы шаблона

0

Предположим, что у нас есть некоторый класс преобразования. Если мы сможем преобразовать из класса T в U, мы автоматически можем преобразовать наоборот.

Я представляю его с классом шаблона и некоторыми специализациями:

template <typename T, typename U>
class Convert;

template <>
class Convert<A,B> {
    static int param() { return 42; }
}

template <>
class Convert<B,A> {
    static int param() { return -Convert<A,B>::param(); }
}

Это работает хорошо, но когда нам нужно добавить новый тип для рутины, мы должны добавить 2 специализации. Можем ли мы уменьшить это число до 1, определив какой-то общий класс обратного шаблона следующим образом:

template <typename T, typename U>
class Convert {
    static int param() { return -Convert<U,T>::param(); }
}

который мог бы работать, если у нас уже есть специализация Convert?

Заранее спасибо.

  • 0
    Вы можете добавить преобразование в определение класса и сделать другую специализацию для двух равных параметров. Тогда вам нужно указать только n * (n-1) / 2 классов.
Теги:
templates
template-specialization

1 ответ

1
Лучший ответ

Вот предложение в моем комментарии:

#include<iostream>
#include<type_traits>

struct A{};
struct B{};
struct C{};

template <typename ... Args>
struct Convert;

template <typename T>
struct Convert<T,T> {
    static int param() { return 0; }
};

template <typename T, typename U>
struct Convert<T,U> {
    static decltype(-Convert<U,T>::param()) param() { return -Convert<U,T>::param(); }
};

template <>
struct Convert<A,B> {
    static int param() { return 42; }
};

template <>
struct Convert<A,C> {
    static int param() { return 43; }
};

template <>
struct Convert<B,C> {
    static int param() { return 44; }
};

int main()
{
    std::cout<<Convert<A,B>::param()<<std::endl;
    std::cout<<Convert<B,A>::param()<<std::endl;
    std::cout<<Convert<A,C>::param()<<std::endl;
    std::cout<<Convert<C,A>::param()<<std::endl;
    std::cout<<Convert<B,C>::param()<<std::endl;
    std::cout<<Convert<C,B>::param()<<std::endl;

    Convert<int,double>::param();
}

Идея состоит в том, чтобы однажды дать общее объявление, а затем сначала указать случай, когда аргументы шаблона равны (что должно давать нуль), а также случай, когда они различны, в которые возвращается преобразованный параметр.

Далее, для n классов вам необходимо предоставить специализации для всех классов n*(n-1)/2 Convert. (в случае, если это необходимо, это может быть дополнительно упрощено путем деривации, например).

  • 0
    Для того же T нам, возможно, понадобится специализация с 2 аргументами. struct Convert<T,T> . В противном случае этот Convert<A,A>::param() не сможет скомпилироваться.
  • 0
    @alexolut: мы делаем, спасибо за исправление
Показать ещё 10 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню