powered by simpleCommunicator - 2.0.58     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Шаблонный параметр с индивидуальной логикой
12 сообщений из 12, страница 1 из 1
Шаблонный параметр с индивидуальной логикой
    #39722716
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет!

Есть некий класс описывающий объект Item
Код: plaintext
1.
2.
3.
4.
class Item
{
	// наполнение не важно
};


Каждый такой Item-объект может быть представлен обычной wchar_t-строкой,
при помощи которой он может быть найден или построен динамически в run-time
в базовом классе Executor. Поэтому у Executor две функции Execute для разных типов параметров
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
class Executor
{
	void Execute(Item* pItem, /*прочие параметры*/....)
	{
		if (pItem && pItem->IsValid())
		{
			ExecuteOneWay(pItem, ....);
		}
		else
		{
			ExecuteAnotherWay(pItem, ....);
		}	
	}
	
	void Execute(const wchar_t* lpItemName, /*прочие параметры*/...);
	{
		if (lpItemName && lpItemName[0] != 0)
		{
			ExecuteOneWayImpl(lpItemName, ....);
		}
		else
		{
			ExecuteAnotherWayImpl(lpItemName, ....);
		}	
	}
}


Класс Executor является предком множества производных классов, каждый из которых решает свою специфическую задачу

Например,
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
class CarExecutor : public Executor
{
	void Go(Item* pItem, /*прочие параметры*/....)
	{
		// что-то делаем здесь
		// иногда этого *что-то* много, иногда нет
	
		Executor::Execute(pItem, .....);
	}
	
	void Go(const wchar_t* lpItemName, /*прочие параметры*/...);
	{
		// что-то делаем здесь
		// иногда этого *что-то* много, иногда нет
	
		Executor::Execute(lpItemName, .....);
	}
	
	void Stop(Item* pItem, /*прочие параметры*/....)
	{
		// что-то делаем здесь
		// иногда этого *что-то* много, иногда нет
	
		Executor::Execute(pItem, .....);
	}
	
	void Stop(const wchar_t* lpItemName, /*прочие параметры*/...);
	{
		// что-то делаем здесь
		// иногда этого *что-то* много, иногда нет
	
		Executor::Execute(lpItemName, .....);
	}
}


Думаю проблема ясна: приходится каждый раз писать две функции для разных типов параметров и казалось бы ответ на данную проблему - шаблоны!
Только вот логика класса Executor не позволяет сделать так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
template<typename T>
void Execute(T* param, /*прочие параметры*/...);
{
	if (param && param[0] != 0)		// первое ОК, второе - бред, если T* - это Item*
	if (param && param->IsValid())		// первое ОК, второе - бред, если T* - это const wchat_t*

	...
}


Первое что пришло в голову использовать type traits и сделать так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
template<typename T>
void Execute(T* param, /*прочие параметры*/...);
{
	auto bIsItem = std::is_same<T, Item>::value;

	if (bIsItem == false) // вроде бы шаблонный класс, а ведет себя как обычный :(,
	{//  тут есть и другие проблемы, если понадобится использовать производный от Item класс (std::is_base_of ? возможно....)
		if (param && param[0] != 0)	 // первое ОК, второе OK, тк теперь мы знаем что T - это строка
		{
			ExecuteOneWayImpl(param, ....);
		}
		else
		{
			ExecuteAnotherWayImpl(param, ....);
		}
	}
	else
	{
		if (param && param->IsValid())	// первое ОК, второе OK, тк теперь мы знаем что T - это Item
		{
			ExecuteOneWayImpl(param, ....);
		}
		else
		{
			ExecuteAnotherWayImpl(param, ....);
		}	
	}		
}


Мне не особо нравится это решение и кажется неэффективным, возможно кто-то предложит другой вариант ?

--------------------------------------------------------------
o(O_O)o
...
Рейтинг: 0 / 0
Шаблонный параметр с индивидуальной логикой
    #39722744
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cerebrum,

Нельзя было написать отдельную специализацию для Executor::Execute<Item>?
...
Рейтинг: 0 / 0
Шаблонный параметр с индивидуальной логикой
    #39722999
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, можно, но пока придумал вот так...

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
template
<
	typename T,
	typename Validator
>
class ItemParamBase
{
public:
	ItemParamBase(T* ptr)	{ m_ptr = ptr;		}

private:	
	T* m_ptr;
	
public:
	operator T*() const	{ return m_ptr;		}
	operator BOOL() const	{ return IsValid();	}

public:
	bool IsValid(void) const
	{
		return Validator::IsValid(m_ptr);
	}
};

// и

template <typename T>
struct StringParamValidator
{
	static bool IsValid(T pValue)	{ return (pValue && pValue[0]);		}
};

template <typename T>
struct ItemParamValidator
{
	static bool IsValid(T pValue)	{ return (pValue && pValue->IsValid());	}
};

// тогда

template <typename T> using ItemParamPtr = ItemParamBase<T, ItemParamValidator<T*>>;
template <typename T> using StringParamPtr = ItemParamBase<T, StringParamValidator<T*>>;

template<typename T>
void Executor::Execute(T* pValue, .....)
{
	if (pValue)
		....
	else
		////
}

// как-то так

Execute(StringParamPtr<const wchar_t>(L"bla-bla-bla"), ....);
Execute(ItemParamPtr<Item>(new Item), .....);


и тогда не придется писать специализации Execute, если мне понадобится изменить что-то в производном от Executor классе, только добавить Validator с нужным функционалом
...
Рейтинг: 0 / 0
Шаблонный параметр с индивидуальной логикой
    #39723216
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немного не понятно.
Если две функции работают с разными параметрами, зачем их собирать в одну, если потом внутри всё равно код разбивается на две части внутренней логикой?

Как раз удобнее оставить 2 (перегруженные) функции, которые принимают Item и wchar, а компилятор сам решит, какую туда подставить.
Item может быть представлен строкой, т.о. Execute(wchar) может формировать Item и звать внутри соответствующую функцию?
...
Рейтинг: 0 / 0
Шаблонный параметр с индивидуальной логикой
    #39723243
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CEMb,

дело в том, что wchar-type это случай, когда клиент Executor'a не имеет возможности выполнить функцию с Item параметром, а Executor (или нижележащие классы) знают как преобразовать имя объекта в объект и затем использовать его. В принципе можно было бы написать сначало получение Item по его имени, а потом использование единственной функции с Item параметром. Функция с wchar это просто для удобства вызова, чтобы каждый раз не приходилось искать Item, тем более что это не всегда возможно на уровне Executor'a.

Для примера, представь что wchar - это имя сервера, а Item - это объект сервера, который исполняет логику. Имя не может исполнять никакой логики, а объект - может. Executor знает как получить объект сервера по его имени и затем выполнить какой-нибудь запрос на его уровне.

Логика примера нааамнооого проще чем то, как обстоит дело в действительности, поэтому неизбежно возникает непонимание: а нафига тебе это вообще надо? Это нормально
...
Рейтинг: 0 / 0
Шаблонный параметр с индивидуальной логикой
    #39723283
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CerebrumCEMb,

дело в том, что wchar-type это случай, когда клиент Executor'a не имеет возможности выполнить функцию с Item параметром, а Executor (или нижележащие классы) знают как преобразовать имя объекта в объект и затем использовать его. В принципе можно было бы написать сначало получение Item по его имени, а потом использование единственной функции с Item параметром. Функция с wchar это просто для удобства вызова, чтобы каждый раз не приходилось искать Item, тем более что это не всегда возможно на уровне Executor'a.

Для примера, представь что wchar - это имя сервера, а Item - это объект сервера, который исполняет логику. Имя не может исполнять никакой логики, а объект - может. Executor знает как получить объект сервера по его имени и затем выполнить какой-нибудь запрос на его уровне.

Логика примера нааамнооого проще чем то, как обстоит дело в действительности, поэтому неизбежно возникает непонимание: а нафига тебе это вообще надо? Это нормально
Это значит, что у тебя просто проблема с проектированием.

Похоже, что задача типовая - фабрика с десериализацией.

Проще сначала создать Item(параметры) или Item(wchar* tag) стандартным образом - конструктором.
...
Рейтинг: 0 / 0
Шаблонный параметр с индивидуальной логикой
    #39723285
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Шаблонный параметр с индивидуальной логикой
    #39723294
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiemarglЭто значит, что у тебя просто проблема с проектированием.
Похоже, что задача типовая - фабрика с десериализацией.
Проще сначала создать Item(параметры) или Item(wchar* tag) стандартным образом - конструктором.

не исключено - код старый и требует основательного рефакторинга и перепроектирования

Пока вернулся к тому что было
...
Рейтинг: 0 / 0
Шаблонный параметр с индивидуальной логикой
    #39723387
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CerebrumЛогика примера нааамнооого проще чем то, как обстоит дело в действительности, поэтому неизбежно возникает непонимание: а нафига тебе это вообще надо? Это нормально
Ну вот я так и заподозрил в начале, что это упрощение.
Но всё равно не пойму, зачем всё в одну функцию. Функция-с-именем, получает объект и скармливает его другой функции, которая знает, что с ним делать.
Я у себя всегда так делаю, когда код обращается к функциональным контейнерам двумя способами: по имени или с объектом. Например, когда надо удалить объект из контейнера, по имени/ключу или по ссылке на сам объект. Одна ищет, вторая ещё раз ищет, но иначе, и удаляет
...
Рейтинг: 0 / 0
Шаблонный параметр с индивидуальной логикой
    #39723395
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CEMbНо всё равно не пойму, зачем всё в одну функцию. Функция-с-именем, получает объект и скармливает его другой функции, которая знает, что с ним делать
потому что задолбался писать по две функции с практически полностью идентичным кодом каждый раз
иногда этого идентичного кода практически нет, а иногда - прилично

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

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

Вся проблема только - найти на это время, среди потока нескончаемых новых задач...
...
Рейтинг: 0 / 0
Шаблонный параметр с индивидуальной логикой
    #39723579
Фотография полудух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
как раз на продумывание архитектуры нужно тратить время, а не код городить ;)
основная работа программиста не в кол-ве строк, а в разработке алгоритмов
...
Рейтинг: 0 / 0
Шаблонный параметр с индивидуальной логикой
    #39724693
Фотография ну я
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
class Executor
{
	void Execute(Item* pItem, const wchar_t* lpItemName, /*прочие параметры*/....)
	{
		if (pItem && pItem->IsValid())
		{
			ExecuteOneWay(pItem, ....);
		}
		else if (lpItemName && lpItemName[0] != 0)
		{
			ExecuteOneWayImpl(lpItemName, ....);
		}
		else
		{
			ExecuteAnotherWay(pItem, ....);
		}	
	}
}
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Шаблонный параметр с индивидуальной логикой
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]