Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Специализрованные методы шаблонного класса, принудительное авто-инстанцирование 
V
    Опции темы
orlangur86
Дата 28.2.2010, 02:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 17.7.2008

Репутация: нет
Всего: нет



Доброго времени суток!
Объясните пожалуйста, если есть возможность, следующую ситуацию.
Имеется шаблон класса, определенный в файле SomeTpl.h
Выглядит следующим образом:
Код

#pragma once

template< class Tp >
class SomeTpl{
private:
    int var1;
public:
    void some_op1();
    void some_op2();

    int getVar();
};
#include "SomeTpl.inl"

Фактические определения методов в файле SomeTpl.inl
Код

template< class Tp >
int SomeTpl<Tp>::getVar()
{
    return var1;
}

template< class Tp >
void SomeTpl<Tp>::some_op1()
{
    var1 = 1;
}

template< class Tp >
void SomeTpl<Tp>::some_op2()
{
    var1 = 2;
}

template<>
void SomeTpl<int>::some_op1()
{
    var1 = 3;
}

template<>
void SomeTpl<int>::some_op2()
{
    var1 = 4;
}


Как видно из кода, определения включают также специализацию методов some_op1 и some_op2 для типа int.
Есть некий файл SomeCpp1.cpp внутри которого выполнено простое включение

#include "SomeTpl.h"

и ничего более.

И есть файл TestPrj.cpp следующего содержания
Код

#include "stdafx.h"
#include <iostream>

#include "SomeTpl.h"

int _tmain(int argc, _TCHAR* argv[])
{
    SomeTpl<double> x1;
    //SomeTpl<int> x2;

    x1.some_op1();
    std::cout<<x1.getVar()<<std::endl;

    //x2.some_op1();
    //std::cout<<x2.getVar()<<std::endl;
}

Как видно, явно инстанцируется только версия класса для типа double. Ликовщик ругается и говорит, что
1>TestPrj.obj : error LNK2005: "public: void __thiscall SomeTpl<int>::some_op1(void)" (?some_op1@?$SomeTpl@H@@QAEXXZ) already defined in SomeCpp1.obj
1>TestPrj.obj : error LNK2005: "public: void __thiscall SomeTpl<int>::some_op2(void)" (?some_op2@?$SomeTpl@H@@QAEXXZ) already defined in SomeCpp1.obj
В асм. листинге кода для TestPrj присутствует код для SomeTpl<int>::some_op1 и SomeTpl<int>::some_op2
т.е. специализация для int тоже вдруг оказывается инстанцированной, хотя об этом никто не просил. Почему так получается?

Если задать отдельную специализацию для класса в таком виде:
Код

template<>
class SomeTpl<int>{
private:
    int var1;
public:
    void some_op1()
    {
        var1 = 3;
    }
    void some_op2()
    {
        var1 = 4;
    }

    int getVar(){ return var1; }
};

то это прокатывает, но приходится дублировать уже написанное. Как с этим быть? Может я что-то не так понимаю?

Заранее мерси smile
PM MAIL   Вверх
baldina
Дата 28.2.2010, 02:46 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Потому что в заголовках можно определять только inline функции, иначе имеем в каждой единице трансляции копию функции.
Цитата

специализация для int тоже вдруг оказывается инстанцированной, хотя об этом никто не просил

не вдруг. не только не просил, а в явном виде определил функции smile

короче - перед каждой функцией в SomeTpl.inl надо поставить inline или определить эти функции в отдельном .cpp
PM MAIL   Вверх
orlangur86
Дата 28.2.2010, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 17.7.2008

Репутация: нет
Всего: нет



baldina,  спасибо!
С inline-ом получилось. А вот на счет объявления специализаций в отдельном срр я не понял. Перенес эти специализации в отдельный SpecCpp.cpp
Код

#include "stdafx.h"

#include "SomeTpl.h"

template<>
inline void SomeTpl<int>::some_op1()
{
    var1 = 3;
}

template<>
inline void SomeTpl<int>::some_op2()
{
    var1 = 4;
}


компилятор ругается
speccpp.cpp(9) : error C2908: explicit specialization; 'void SomeTpl<Tp>::some_op1(void)' has already been instantiated
        with
        [
            Tp=int
        ]
speccpp.cpp(15) : error C2908: explicit specialization; 'void SomeTpl<Tp>::some_op2(void)' has already been instantiated
        with
        [
            Tp=int
        ]

где он уже успел инстанцировать эти методы для типа int? 

PM MAIL   Вверх
baldina
Дата 28.2.2010, 17:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



в SpecCpp.cpp они должны быть не inline. "где он успел" обычно компилятор пишет. возможно осталась строчка #include "SomeTpl.inl" в SomeTpl.h

вот так:
Код

// SomeTpl.h
template< class Tp >
class SomeTpl{
private:
    int var1;
public:
    void some_op1();
    void some_op2();
    int getVar();
};


Код

// SomeTpl.cpp
#include <SomeTpl.h>
template<>
void SomeTpl<int>::some_op1()
{
    var1 = 3;
}
template<>
void SomeTpl<int>::some_op2()
{
    var1 = 4;
}


Код

// test.cpp
#include <iostream>
#include "SomeTpl.h"
int main ()
{
    SomeTpl<double> x1;
    //SomeTpl<int> x2;
    x1.some_op1();
    std::cout<<x1.getVar()<<std::endl;
    //x2.some_op1();
    //std::cout<<x2.getVar()<<std::endl;
}

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0884 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.