У меня есть функция, принимающая в качестве аргумента шаблонный класс с несколькими параметрами (см. "Func2" в следующем коде). Я бы хотел, чтобы функция могла принимать в качестве аргумента класс, унаследованный от типа agument, и автоматически разрешать типы шаблонов с помощью восходящего преобразования. В следующем примере это нормально для функции «func1», но, по-видимому, невозможно напрямую, когда аргумент является классом с несколькими шаблонами, как для функции «func2».

В сообщении об ошибке говорится: «Шаблон-кандидат проигнорирован: ошибка замены: аргумент шаблона шаблона имеет параметры, отличные от его соответствующего параметра шаблона шаблона» Я понимаю (и частично согласен) с сообщением. Но то же самое и с func1, и он работает нормально.

Итак, мой вопрос: есть ли способ обработать переменную 'd' как тип 'C' с помощью автоматического повышения качества при использовании функции? И если да, то как? Я использую Xcode 5.1.1, clang-503.0.40. и вариант C ++ 11. Спасибо

template <class T1>
class A {};

class B : public A<int> {};

template <template <class T1> class T, class T1 >
void func1(T<T1> _arg) {}

template <class T1, class T2>
class C {};

template <class T1>
class D : public C<T1,int> {};

template <template <class T1, class T2> class T, class T1, class T2>
void func2(T<T1,T2> _arg) {}


int main() {
    A<int> a;
    B b;
    func1(a);//works
    func1(b);//works, T1 is resolved

    C<float,int> c;
    D<float> d;
    func2(c);//works
    func2(d);//doesn't work,compilation error message: "Candidate template ignored: substitution failure : template template argument has different template parameters than its corresponding template template parameter"

    return 0;
}
2
brahmin 14 Окт 2014 в 13:52

2 ответа

Лучший ответ

Хорошо, поэтому лучший вариант, который я нашел, следующий. Идея состоит в том, чтобы заставить «D» поверить, что это класс с несколькими шаблонами, но на самом деле один из параметров шаблона предназначен только для определенного типа (int). Таким образом, «D2» является своего рода классом с одним шаблоном и классом с двумя шаблонами. При определении шаблонного класса D по-прежнему существует одна частичная специализация, но на самом деле это всего лишь обычное определение класса D.

template <class T1, class T2>
class C {};

template <class T1, class T2=int>
class D;

template <class T1>
class D<T1,int> : public C<T1,int> {};

template <typename T1>
using D2 = D<T1>;

template <template <class T1, class T2> class T, class T1, class T2>
void func2(T<T1,T2> _arg) {}

int main()
{
    C<float,int> c;
    D2<float> d;
    func2(c);//works
    func2(d);//works

    //instantiation tests:
    D<float> test1;//works -> normal
    D<float, int> test2;//works -> not ideal but well ok
    D<float, float> test3;//doesn't work -> also normal. States: "Implicit instantiation of undefined template 'D<float, float>' "

    return 0;
}
0
brahmin 14 Окт 2014 в 16:06

Нет, нет возможности делать то, что ты пытаешься сделать.

Однако вы можете использовать псевдоним, если ваш компилятор их поддерживает:

template < typename T >
using D = C<T,int>;

Я считаю, что это должно прекрасно соответствовать вашему шаблону функции.

Если вы пытаетесь заставить D вести себя по-другому, вы создадите частичную специализацию C.

1
Edward Strange 14 Окт 2014 в 10:01