Частичная специализация с использованием квалифицированного имени - PullRequest
0 голосов
/ 08 января 2020

Я пытаюсь частично специализировать шаблон для мета-функции и столкнулся с проблемой.

Я специализировал шаблон следующим образом:

template <typename A, typename B>
struct Foo;

template <typename A, typename B1>
struct Foo<A, typename A::template Bar<B1>> {
    /* use both A and B1*/
};

template <typename A, typename B1>
struct Foo<A, typename A::template Xyz<B1>> {
    /* use both A and B1*/
};

Однако это приводит к (Visual Studio 2019 ) в

Error C2764: 'B1': template parameter not used or deducible in partial specialization 'Foo<A,A::Bar<B1>>' (5, 47)

Я предполагаю, что это потому, что я использовал параметр шаблона A в качестве спецификатора в специализации (typename A::template Bar<B1>).

Есть ли способ обойти это и использовать параметры в специализациях шаблонов в качестве квалификаторов?

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

Ответы [ 2 ]

3 голосов
/ 08 января 2020

Использование шаблона Параметр шаблона может сработать:

template <typename A, typename B>
struct Foo;

template <typename TA, template<class> class TBar,  typename B1>
struct Foo<TA, TBar<B1>> {};

Учитывая

struct A
{
    template<class T>
    struct Bar {};
};

, вы можете сформировать

Foo<A, A::Bar<int>> x;

, и это будет выводить A A::Bar и int в специализации для вас. Но обратите внимание, что не делается никаких попыток проверить, что A в A::Bar соответствует A, указанному в качестве первого параметра шаблона; неясно, что вы ожидаете, скажем, для Foo<double, A::Bar<int>>.

https://godbolt.org/z/hGhsZm

1 голос
/ 08 января 2020

Я предполагаю, что это потому, что я использовал параметр шаблона A в качестве квалификатора в специализации (typename A :: template Bar).

Я так не думаю.

Предположим, что A выглядит следующим образом

struct A
 { 
   template <typename B>
   using Bar = int; 
 };

и что вы определяете Foo<A,A::Bar<B1>>.

Но A::Bar<B1> равно int!

Итак, вы определяете Foo<A, int>.

Как может компилятор выводить B1 из int?

Мне кажется, что это невозможно.

Возможное решение (в зависимости от ваших потребностей): если вам нужно специализироваться через B1, но вам нужно A::Bar<B1> внутри Foo, вы можете использовать B1 как второй параметр и A::Bar<B1> как использование типа внутри Foo

template <typename A, typename B1>
struct Foo<A, B1> {
   using bType = A::template Bar<B1>;
};
...