использование классов шаблонов в качестве параметров метода

У меня есть два класса шаблонов: Class1‹ S > и Class2‹ T >. В Class2‹ T > есть метод, который имеет в качестве параметра указатель на объект Class1‹ S >. Должен ли я тогда переопределить class2‹ T > на class2‹ S, T >? или есть другое лучшее решение? Проблема в том, что у меня могут быть новые методы, ссылающиеся на объекты других классов шаблонов в качестве параметров. Поэтому я хотел бы избежать наличия чего-н. например: class2‹ S, T, U ...>

template < class S >
class Class1{
    public:
        ...
    private:
        ...
};

template < class T >
class Class2{
    public:
        ...
        Class2<T> * doSomething(Class1<S> * );
        ...
    private:
        ...
};

template < class S, class T >
class Class2{
    public:
        ...
        Class2<T> * doSomething(Class1<S> * );
        ...
    private:
        ...
};

person Javier    schedule 15.11.2010    source источник


Ответы (1)


Тип объекта, на который действует Class2::doSomething, не должен быть частью типа Class2. Поэтому создайте Class2::doSomething() шаблон функции-члена:

template < class T >
class Class2{
    public:
        ...
        template<class S> Class2<T> * doSomething(Class1<S> * );
        ...
    private:
        ...
};

ИЗМЕНИТЬ:

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

template<class FooType> class Foo
{
};

template<class BarType> class Bar
{
public:
    template<class FooType> Bar<BarType>* doSomething(Foo<FooType>* foo);
};

template<typename BarType> template<typename FooType> Bar<BarType>* Bar<BarType>::doSomething(Foo<FooType>* foo)
{
    return 0;
}

int main()
{
    Foo<unsigned> foo_1;
    Bar<double> bar_1;
    Bar<double> * bar_copy = 0;
    bar_copy = bar_1.doSomething<unsigned>(&foo_1);
    return 0;
}
person John Dibling    schedule 15.11.2010
comment
Спасибо за Ваш ответ. И когда я инициализирую/использую объекты, это будет sth. например: Class1‹int› objClass1; Class2‹float› objC2_1, *objC2_2; objC2_2 = objC2_1.doSomething(&objClass1); правильно? - person Javier; 16.11.2010
comment
+1, хорошее объяснение сложного внестрочного синтаксиса. Я думаю, что <unsigned> в bar_1.doSomething<unsigned>(&foo_1); не является необходимым - разве это не будет выведено? - person j_random_hacker; 16.11.2010
comment
@j: наверное, правда. я не могу проверить в данный момент, и я обычно просто ввожу параметры шаблона явно - person John Dibling; 16.11.2010
comment
@John, определение/реализация класса шаблона разделены (файлы .h и .cpp), а также я включаю файл .inc в конец файла .cpp для инициализации классов шаблонов, например (bar-impl. inc) класс шаблона Bar‹float›; класс шаблона Bar‹int›; то же самое для foo-impl.inc: класс шаблона Foo‹int›; класс шаблона Foo‹float›; (www.parashift.com/c++-faq-lite/templates.html#faq-35.13). Теперь я получаю сообщение : /tmp/ccBySVYZ.o: В функции main': bar.cpp:(.text+0x19f):undefined reference to void Bar‹float›::doSomething‹float›(Foo‹float›*)’ collect2:ld вернул 1 статус выхода make: *** [imagetest] Error 1 - person Javier; 16.11.2010
comment
@Javier: Вы не можете поместить определения шаблонов в файл CPP, по крайней мере, без некоторой акробатики. Вы можете поместить определение в файл HPP, а затем #include этот файл HPP непосредственно из файла заголовка. Вот одна ссылка: stackoverflow.com/questions /2185954/ - person John Dibling; 16.11.2010
comment
@John, спасибо за ссылку. Однако я хотел бы использовать явное создание экземпляров шаблонов. До сих пор я мог объявить класс шаблона в файле .h, его реализацию в файле .cpp и явное создание экземпляров. класса шаблона в файле .inc (класс шаблона Bar‹float›; ...). Я хотел бы следовать тому же протоколу, поэтому я сомневаюсь, что в основном это будет экземпляр шаблона для метода doSomething? Кстати, вы использовали имя типа вместо класса, шаблон‹имя типа BarType› шаблон‹имя типа FooType›… почему это не может быть шаблон‹класс BarType› шаблон‹класс FooType›? - person Javier; 16.11.2010
comment
Вы можете сделать явное создание экземпляра. Некоторое время назад я ответил на вопрос, который точно объясняет, как это сделать, но сейчас я не могу его найти. Буду дальше смотреть. - person John Dibling; 16.11.2010
comment
@John, что, если у меня есть метод в классе Bar, который возвращает указатель на класс Foo: template‹class FooType› Foo‹FooType›* doSomething1(int); В этом случае у меня возникли некоторые проблемы: ошибка: нет соответствующей функции для вызова Bar‹float›::doSomething1(int&) - person Javier; 18.11.2010