Может ли параметром функции быть имя типа?

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Absurd писал(а):В С++ если тебе нужно варьировать поведение функции в зависимости от типа аргумента принято применять шаблоны
Ну напишу я шаблон. Дальше что? Он всё равно будет принимать переменную, а мне надо сам тип передать.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Сионист писал(а):Мне нужен параметр функции, аналогичный операнду sizeof.

В С++ если тебе нужно варьировать поведение функции в зависимости от типа аргумента принято применять шаблоны и частичную специализацию.

Вот пример из моего кода - здесь я вычислял ширину ребра графа для graphviz. Весовые коэффициенты разных графов имеют разный тип, так что мне пришлось написать шаблон который их конвертирует в double. Поскольку один из типов CostGraph::Cost не конвертируется в double тривиальным способом, мне пришлось сделать _частичную специализацию_ шаблона специально для CostGraph::Cost.

Код: Выделить всё

template<typename T> struct _2double {
  static double calc(T arg);
};

template<typename T> double _2double<T>::calc(T arg) {
  return double(arg);
}

template<> double _2double<CostGraph::Cost>::calc(CostGraph::Cost arg)
{
  using ddur = std::chrono::duration<double>;
  return std::chrono::duration_cast<ddur>(arg).count();
}

template<typename T> int getWidth(T val, T maxVal)
{
  double c1 = _2double<T>::calc(val);
  double c2 = _2double<T>::calc(maxVal);
  return static_cast<int>(1. + 29. * std: :p ow(c1 / c2, 2.));
}
Если нужно вычислить разную информацию о типе используй <type_traits> http://en.cppreference.com/w/cpp/header/type_traits
2B OR NOT(2B) = FF
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

WinMain писал(а):Попробуй использовать шаблон...

Код: Выделить всё

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

template <typename T>
void PrintTypeInfo(T value)
{
	size_t size = sizeof(value);
	const type_info& ti = typeid(value);
	printf("%d, %s\n", size, ti.name());
};

int _tmain(int argc, _TCHAR* argv[])
{
	PrintTypeInfo(argc);
	PrintTypeInfo(argv);
	PrintTypeInfo(_tmain);

	_gettch();
	
	return 0;
}
argc и argv - это переменные. В месте вызова ни одной переменной того типа, о котором надо вывести информацию, не существует.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Какую переменную? Шаблоны вычисляются в момент компиляции, там нет никаких переменных.
2B OR NOT(2B) = FF
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

И вызываются тоже в момент компиляции? Однако!
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Сионист писал(а):И вызываются тоже в момент компиляции? Однако!

Что ты вкладываешь в глагол "вызывается"? Если ты имеешь в виду вызов шаблонной функции, то после компиляции ее не существует, а есть N специализаций для всех типов, для которых она была инстанциирована.
2B OR NOT(2B) = FF
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

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

Код: Выделить всё

template <typename T>
void ShowSize()
{
   std::cout << sizeof(T) << std::endl;
}

...

ShowSize<int>();
ShowSize<double>();

class A {};
ShowSize<A>();
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Romeo писал(а):Передать тип мы не можем в принципе, так как тип - это понятия времени компиляции.
Не в принципе. При наличии рефлекшена можно передать java.lang.Class или нечто подобное. Только если чел подобный Сионисту пойдет джуниором на жабу могут случиться разные неприятности.
2B OR NOT(2B) = FF
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Java и C# рефлекшены нам не доступны, к сожалению. Мы говорим сейчас исключительно о С++.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Romeo писал(а):Java и C# рефлекшены нам не доступны, к сожалению. Мы говорим сейчас исключительно о С++.

Когда питаешься понять что хочет сионист мозг наполняют антитела к неточным определениям. "Передать тип мы не можем в принципе" - в принципе типы передаются. Но не в С++, точнее не в его стандартном подмножестве.
2B OR NOT(2B) = FF
Ответить