2015-04-14 3 views
0

Мне интересно, какой хороший шаблон дизайна для следующего сценария. Три вопроса:C++ Функции вызова с различными сигнатурами, в зависимости от типа

1) У меня есть шаблонный «Контейнер» для подклассов «Производный». Я хочу иметь возможность хранить различные типы объектов шаблона (любого типа A или B, оба подкласса Derived) в векторе. Как это сделать?

2) У меня есть функция «func», специфичная для шаблона, которая работает с контейнерами и имеет переменное количество аргументов, в зависимости от того, является ли тип шаблона контейнера A или B. Каков хороший способ проверить типы шаблонов в чтобы вызвать соответствующую функцию?

3) Имеют ли шаблоны даже смысл для этого прецедента?

#include <iostream> 
#include <string> 
#include <vector> 
#include <memory> 

using namespace std; 

struct Derived {}; 

struct A : Derived { 
    int x; 
    A(int x) : x(x) {} 
}; 
struct B : Derived { 
    bool y; 
    B(bool y) : y(y) {} 
}; 

template <typename T> 
struct Container 
{ 
    T item; 
    Container(T i) : item(i) {} 
}; 

// definition of a template function for type a, with specialization 
void func(Container<A> c, int a, int b) { 
    cout << "update for A called" << endl; 
} 

void func(Container<B> c, bool x) { 
    cout << "update for B called" << endl; 
} 

int main(int argc, char const *argv[]) 
{ 
    Container<A> * foo = new Container<A>(A(1)); 
    Container<B> * bar = new Container<B>(B(true)); 
    // test that func() works 
    func(*foo,1,2); 
    func(*bar,false); 

    vector< Container<Derived>* > vec; 

    // this does not work 
    vec.push_back(unique_ptr< Container<Derived *> >(foo)); 
    vec.push_back(unique_ptr< Container<Derived *> >(bar)); 

    for (Container<Derived>* d : vec) { 
     // how to call the proper func(d)? 
    } 
    return 0; 
} 
+2

[Специализация по шаблону] (http://www.cprogramming.com/tutorial/template_specialization.html)? –

+0

является целью 'Container <>' только для хранения A и B в векторе? или в чем цель? – sp2danny

ответ

1

1) Вы можете хранить указатели на A (типа A *) или указатели на B (типа B *) в std::vector<Derived *>, потому что Derived является базой для A и B. Невозможно сохранить Container<A> и Container<B> в тот же вектор, потому что между ними нет отношения наследования. Это также (косвенно) причина, по которой ваш компилятор отклоняет преобразование foo и bar в unique_ptr<Container<Derived *> >.

2) Ваш func() не является «специфичной для шаблона функцией». Это даже не шаблонная функция. Это функция, которая перегружена, с одним вариантом, который принимает два аргумента, и один вариант, который принимает три.

3) Учитывая, что ваш код недействителен, невозможно сделать вывод, что ваш вариант использования. Учитывая, что вы пытаетесь преобразовать объекты в несвязанные типы, я предполагаю, что ваш прецедент не имеет смысла в C++, не говоря уже об использовании шаблонов для него.

Кроме того, не используйте Java (или любой другой язык, о котором вы думаете) в C++, потому что они не работают одинаково. В частности,

Container<A> * foo = new Container<A>(A(1)); 
Container<B> * bar = new Container<B>(B(true)); 
func(*foo,1,2); 
func(*bar,false); 

не нужно. Он используется в Java по разным причинам, которые недействительны на C++, даже если код компилируется. Вместо этого сделайте это;

Container<A> foo A(1); 
Container<B> bar B(true); 
func(foo,1,2); 
func(bar,false); 

Это действительный и безопасный C++ (и не будет работать на Java, но это уже другая история).

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