2015-03-02 5 views
2

Итак, во-первых, извинения за терминологию - я не уверен, что прототип шаблона - правильный термин. Под этим я подразумеваю:Прохождение шаблона шаблона в качестве аргумента шаблона - возможно ли это?

template <class T, class X> 
class TemplatePrototype 
{ 
// code 
}; 

У меня есть ситуация, когда у меня есть функция, которая создает объект шаблона на основе аргументов шаблона этой функции.

template <class T, class X> 
void doSomething() 
{ 
    TemplatePrototype<T, X> aTemplateTX; 
    aTemplateTX.doSomethingElse(); 
} 

Однако, существует около 15 различных версий TemplatePrototype, которые все имеют один и тот же интерфейс, но различное исполнение (TemplatePrototype предоставляется другой библиотекой). В результате, у меня есть много кода, который выглядит следующим образом:

template <class T, class X> 
void doSomethingWithOne() 
{ 
    TemplatePrototypeOne<T, X> aTemplateTX; 
    aTemplateTX.doSomethingElse(); 
} 

template <class T, class X> 
void doSomethingWithTwo() 
{ 
    TemplatePrototypeTwo<T, X> aTemplateTX; 
    aTemplateTX.doSomethingElse(); 
} 

Как следствие архитектуры, я нужно обязательно знать, какие TemplatePrototype я собираюсь использовать , прежде чем я знаю фактические типы T и X. Я бы как, чтобы увидеть что-то вроде этого:

template <class T, class X, class Prototype> 
void doSomething() 
{ 
    Prototype<T, X> aPrototype; 
    aPrototype.doSomething(); 
} 

Но где я определенную часть аргументов шаблона заранее - т.е. я указываю Prototype Befo re Я знаю T и X. Очевидно, что это невозможно в C++.

В равной степени я не могу передать Prototype в качестве аргумента шаблона, потому что он все равно приведет к огромному количеству дубликатов кода.

Некоторые важные факты: Я знаю диапазон всех возможных входов.

Так что я мог бы теоретически использовать макрос, чтобы определить каждую возможную специализацию по шаблону и вставить их в контейнер, который я бы использовал для доступа к специализации, в которой я нуждаюсь. Тем не менее, я ищу более «элегантное» решение - можно ли пропустить шаблонные прототипы, не специализируясь на них как аргумент класса шаблона, а затем создавать экземпляры позже, когда вызывается функция? Пример:

template <class Prototype> 
class Holder 
{ 
    template <class T, class X> 
    void doSomething() 
    { 
     Prototype<T, X> aPrototype; 
     aPrototype.doSomethingElse(); 
    } 
}; 

Насколько я знаю, что это невозможно, но мне было интересно, если SO сообщество некоторые люди, которые знают решение?

EDIT:

Так что я реализовал это, как мое решение, благодаря ответы на приведенные ниже!

#include <iostream> 

template <typename T> 
struct Foo 
{ 
     Foo() { aPtr = 0; } 
     T* aPtr; 
}; 

template <template<typename> class C> 
struct Bar 
{ 
     template <class T> 
     void doSomething() 
     { 
       C<T> aClass; 
       if (aClass.aPtr) 
         std::cout << "Hello world" << std::endl; 
     } 
}; 


int main() 
{ 
     Bar<Foo> aFoo; 
     aFoo.doSomething<int>(); 

     return 0; 
} 

Это позволяет мне определить, какие TemplatePrototype я хотел бы использовать, перед тем я могу знать параметры шаблона.

+1

Существует такая вещь, как параметры шаблона шаблона: один можно написать 'шаблон <шаблон <класс, класс> класс Prototype> ... { Prototype ...} ' – ach

+0

Обратите внимание: параметры' template' 'template'ы кажутся очень удобными, пока вы не попытаетесь использовать их в нетривиальном виде. Затем вы начинаете сталкиваться с проблемами, вызванными фактами: (1) фиксировано количество шаблонных параметров для шаблона и (2) тип класса теперь полностью исправлен. Не стесняйтесь дать им попробовать, но имейте в виду, что вам может понадобиться найти другое решение. – Mehrdad

+0

@Mehrdad Нет, их количество не фиксировано. Существуют различные шаблонные параметры шаблона;) См. Мой обновленный ответ. – leemes

ответ

4

Да, используйте параметр шаблона шаблона, например.

template <typename T> 
struct Foo 
{ 
}; 

template <template<typename> class C> 
struct Bar 
{ 
}; 

затем

Bar<Foo> b; 
+0

Огромное спасибо - это решило мою точную проблему в броске, теперь для ее реализации для производственного кода. Очень благодарен :) –

3

Вы ищете параметров шаблона шаблон.

В списке параметров шаблона, а не просто:

class TemplatePrototype 

указать свой прототип в качестве шаблона класса, который сам по себе имеет два параметра типа шаблона (не давая им имя здесь), как:

template<class,class> class TemplatePrototype 
//^^^^^^^^^^^^^^^^^^^ 

Это приведет к функции, как:

template <class T, class X, 
      template<class,class> class TemplatePrototype> 
void doSomething() 
{ 
    TemplatePrototype<T, X> aTemplateTX; 
    aTemplateTX.doSomethingElse(); 
} 

Призыва examp ль:

doSomething<T, X, TemplatePrototypeOne>(); 

Чтобы стать независимым от числа параметров шаблона вы передаете на свой «прототип» (здесь это было 2, а именно T и X), вы можете использовать VARIADIC шаблонов (так как C++ 11).

Для этого сначала переместите параметр шаблона прототипа первой позиции:

template <template<class,class> class TemplatePrototype, 
      class T, class X> 

Затем замените class T, class X с class ...Ts, который является заполнителем из произвольного числа параметров типа. Кроме того, в списке параметров шаблона шаблона замените class,class на class.... И в инстанцировании внутри реализации функции замените <T, X> на <Ts...>, чтобы «развернуть» пакет параметров.

Результат будет выглядеть следующим образом:

template <template<class...> class TemplatePrototype, 
      class ... Ts> 
void doSomething() 
{ 
    TemplatePrototype<Ts...> aTemplateTs; 
    aTemplateTs.doSomethingElse(); 
} 

Live demo

+0

Спасибо - это научило меня значительную сумму! Я хотел бы принять оба ответа как можно лучше, если бы мог! Ответ Нима более прямо ответил на мой конкретный вопрос, но мне плохо, что я тоже не могу это принять, потому что вы определенно дали мне гораздо больше информации! –

Смежные вопросы