Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.03.2012, 20:01   #1
Diego__
Форумчанин
 
Регистрация: 12.08.2009
Сообщений: 118
По умолчанию использование шаблонов

добрый день. Есть шаблонный класс Derived, который наследуется от передаваемого в качестве шаблонного параметра типа
Код:
template <class Base>
class Derived : public Base
{
public:
	Derived(){}

	template<typename T1>
	Derived(T1 a1) :
		Base(a1)
	{}
		
	//...

	template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
	Derived(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10) :
		Base(a1, a2,a3, a4, a5, a6, a7, a8, a9, a10)
	{}

};
и есть перегруженные методы для создания умных указателей на интерфейс Base класса
Код:
template<typename Interface, typename Implementation>
inline boost::shared_ptr<Interface> MakeInterface()
{
	typedef Derived<Implementation> SharedImplementation;
	typedef boost::shared_ptr<SharedImplementation> SharedImplementationPtr;

	SharedImplementationPtr impl(new SharedImplementation());
	boost::shared_ptr<Interface> intrf(impl);

	return intrf;
}

template<typename Interface, typename Implementation, typename T1>
inline boost::shared_ptr<Interface> MakeInterface(T1 a1)
{
	typedef Derived<Implementation> SharedImplementation;
	typedef boost::shared_ptr<SharedImplementation> SharedImplementationPtr;

	SharedImplementationPtr impl(new SharedImplementation(a1));
	boost::shared_ptr<Interface> intrf(impl);

	return intrf;
}

// ....

template<typename Interface, typename Implementation, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
inline boost::shared_ptr<Interface> MakeInterface(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10)
{
	typedef Derived<Implementation> SharedImplementation;
	typedef boost::shared_ptr<SharedImplementation> SharedImplementationPtr;

	SharedImplementationPtr impl(new SharedImplementation(a1, a2,a3, a4, a5, a6, a7, a8, a9, a10));
	boost::shared_ptr<Interface> intrf(impl);
	
	return intrf;
}
Возможно ли это зарефакторить, чтобы для каждого числа переменных не писать отдельные перегрузки?
Diego__ вне форума Ответить с цитированием
Старый 04.03.2012, 20:40   #2
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Код:
	
#include <varargs.h>

template <class Ext, class Imp, class T > 
void __cdecl varargfunc(T, ...);
Вы об этом, если я правильно понял?
EUGY вне форума Ответить с цитированием
Старый 04.03.2012, 20:43   #3
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

google variadic templates.
_Bers вне форума Ответить с цитированием
Старый 04.03.2012, 20:53   #4
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Код:
	
#include <varargs.h>

template <class Ext, class Imp, class T > 
void __cdecl varargfunc(T, ...);
Вы об этом, если я правильно понял?
Элипсы в конструкторах, помноженные на особенности шаблонов - верное UB, о чем писали и Александресску, и Джосасис

Если очень нужно родить оное при отсутствии поддержки нового стандарта, то можно глянуть в сторону "листов параметров" (см библиотека Loki, Александресску).

Либо, есть довольно простой для понимания, но топорный в плане реализации (и кстати, очень даже быстрый) - перегрузка шаблонных конструкторов.

Пример топора:

Код:
template<class tClient, int Size=0> class TImpl
{
    #define Placement new(&(Impl[0]))tClient
    #define pClient (tClient*) (&(Impl[0]))
public:
    ~TImpl() { (pClient)->~tClient(); }
public:
    template<Gen_Class_arg1> TImpl() { Placement(); }
    template<Gen_Class_arg1> TImpl(Gen_Arg_con1) { Placement(Gen_ListParam1); }
    template<Gen_Class_arg2> TImpl(Gen_Arg_con2) { Placement(Gen_ListParam2); }
    template<Gen_Class_arg3> TImpl(Gen_Arg_con3) { Placement(Gen_ListParam3); }
    template<Gen_Class_arg4> TImpl(Gen_Arg_con4) { Placement(Gen_ListParam4); }
    template<Gen_Class_arg5> TImpl(Gen_Arg_con5) { Placement(Gen_ListParam5); }
    template<Gen_Class_arg6> TImpl(Gen_Arg_con6) { Placement(Gen_ListParam6); }
    template<Gen_Class_arg7> TImpl(Gen_Arg_con7) { Placement(Gen_ListParam7); }

    tClient* operator ->() { return  pClient;    }
    void Check() { LOKI_STATIC_CHECK(Size>=sizeof(tClient), Impl_Size); }
private:
    char Impl[Size];
    
    #undef Placement
    #undef pClient
};
Где макросы подключаются отдельно и имеют вид:

Код:
//макросы создают набор макро-подстановок , которые могут понадобится для создания универсальных шаблонных методов
//способных принять любые комбинации типов 7ми аргументов
#define Gen_A(i) a##i& v##i
#define Gen_AA(i) class a##i

//лист параметров для шапки шаблона
#define Gen_Class_arg1                 Gen_AA(1)
#define Gen_TClass_arg1 template <Gen_Class_arg1>

#define Gen_Class_arg2 Gen_Class_arg1, Gen_AA(2)
#define Gen_TClass_arg2 template <Gen_Class_arg2>

#define Gen_Class_arg3 Gen_Class_arg2, Gen_AA(3)
#define Gen_TClass_arg3 template <Gen_Class_arg3>

#define Gen_Class_arg4 Gen_Class_arg3, Gen_AA(4)
#define Gen_TClass_arg4 template <Gen_Class_arg4>

#define Gen_Class_arg5 Gen_Class_arg4, Gen_AA(5)
#define Gen_TClass_arg5 template <Gen_Class_arg5>

#define Gen_Class_arg6 Gen_Class_arg5, Gen_AA(6)
#define Gen_TClass_arg6 template <Gen_Class_arg6>

#define Gen_Class_arg7 Gen_Class_arg6, Gen_AA(7)
#define Gen_TClass_arg7 template <Gen_Class_arg7>


//лист аргументов с типами для списка аргументов функции
#define Gen_Arg_con0                void
#define Gen_Arg_con1               Gen_A(1)
#define Gen_Arg_con2 Gen_Arg_con1, Gen_A(2)
#define Gen_Arg_con3 Gen_Arg_con2, Gen_A(3)
#define Gen_Arg_con4 Gen_Arg_con3, Gen_A(4)
#define Gen_Arg_con5 Gen_Arg_con4, Gen_A(5)
#define Gen_Arg_con6 Gen_Arg_con5, Gen_A(6)
#define Gen_Arg_con7 Gen_Arg_con6, Gen_A(7)

//лист аргументов без типов для списка аргументов вызываемой функции
#define Gen_ListParam0                void
#define Gen_ListParam1                 v1
#define Gen_ListParam2 Gen_ListParam1, v2
#define Gen_ListParam3 Gen_ListParam2, v3
#define Gen_ListParam4 Gen_ListParam3, v4
#define Gen_ListParam5 Gen_ListParam4, v5
#define Gen_ListParam6 Gen_ListParam5, v6
#define Gen_ListParam7 Gen_ListParam6, v7
Зато при поддержке variardic template можно уже спокойно вытворять такие вещи:

Код:
template< class Val >class SwithClass
{
public:
    SwithClass( const Val & v ):val(v){}
    void operator() (){}

    template < class E, class F, class ... Args > //<--- Внимательно смотрим сюда
    void operator() ( E e, F f, Args ... args )  //<--- И сюда
    {
        if( e==val ) { f(); }
        else   {  (*this)( args... );   } //<--- И сюда
    }

private:
    Val val;
};
template< class Val > SwithClass<Val> Swith( const Val& v ) { return SwithClass<Val>(v); }

#define foo(arg)  arg, [](){ std::cout <<"x="<< arg << std::endl; }

int main()
{
  int x = 4;

  Swith( x ) ( foo(1) ,foo(4) );
  return 0;
}
_Bers вне форума Ответить с цитированием
Старый 04.03.2012, 21:35   #5
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Цитата:
... верное UB, о чем писали и Александресску, и Джосасис
Этим парням виднее (правда второго не знаю), и где уж нам со свечным огарком...
Но если есть возможность выяснить длину типов, переданных в переменном аргументе то почему бы нет

variardic template - конечно сладко выглядит.
Примеры видел, но на практике не встречал.
Как вообще поэксперементировать?
Какой-то компилятор прикрутить к студии?
EUGY вне форума Ответить с цитированием
Старый 04.03.2012, 22:00   #6
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Этим парням виднее (правда второго не знаю), и где уж нам со свечным огарком...
Но если есть возможность выяснить длину типов, переданных в переменном аргументе то почему бы нет

variardic template - конечно сладко выглядит.
Примеры видел, но на практике не встречал.
Как вообще поэксперементировать?
Какой-то компилятор прикрутить к студии?
Студия не поддерживает variardic temlate, и в ближайшее время не будет поддерживать. Хотя вот читал переписку между разработчиками студии и пользователями. Разработчики заявляют, что из-за всех сил лоббируют руководство внести эту фичу в новую версию студии. Они этим "как бы занимаются".

Лично я передислоцировался на QtCreator, а компилирую при помощи mingw-4.6.2+boost-1.48.0
_Bers вне форума Ответить с цитированием
Старый 13.03.2012, 01:08   #7
Diego__
Форумчанин
 
Регистрация: 12.08.2009
Сообщений: 118
По умолчанию

Не до конца понял пример, но то, что хотел сделал. Спасибо за ответы
Diego__ вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Переделка шаблонов ! ! ! Fanat31 WordPress и другие CMS 2 22.01.2011 12:42
редактор шаблонов Domanoff WordPress и другие CMS 4 14.01.2011 11:56
Создание шаблонов artemavd Общие вопросы Delphi 4 29.09.2010 17:21
Использование шаблонов s180 Microsoft Office Word 5 10.12.2009 16:17