И кроме примера pi, как бы он работал с неконстантными переменными?
В настоящее время, похоже, экземпляры переменных отдельно для типа. то есть вы можете назначить 10 n<int>
, и это будет отличаться от определения шаблона.
template<typename T>
T n = T(5);
int main()
{
n<int> = 10;
std::cout << n<int> << " "; // 10
std::cout << n<double> << " "; // 5
}
Если декларация const
, это только для чтения. Если это constexpr
, как и все объявления constexpr
, у него мало пользы вне constexpr
(ressions).
Кроме того, что мы можем иметь эту функцию только обертывание переменной в шаблонной структуре или класса, как это делает соединение с преобразования типов?
Это должно быть простое предложение. Я не могу понять, как это сильно влияет на преобразования типов. Как я уже сказал, тип переменной - это тип, с которым вы создавали шаблон. то есть decltype(n<int>)
является int. decltype((double)n<int>)
- двойной и так далее.
Любой пример использования, чтобы понять, как максимально использовать такую функцию и какова его цель?
N3651 содержит краткое обоснование.
Увы, существующие правила C++ не позволяют объявление шаблона объявить переменную. Там хорошо известные способы их решения для этой проблемы:
• использование constexpr членов статических данных шаблонов классов
• шаблоны функций Использование constexpr возвращения требуемых значений
Эти обходные пути были известны десятилетиями и хорошо документированы. Стандартные классы, такие как std :: numeric_limits, являются архетипическими примерами . Хотя эти обходные пути не идеальны, их недостатки были в некоторой степени допустимы, потому что в эпоху C++ 03 только простые константы встроенных типов пользовались неограниченной прямой и эффективной поддержкой времени компиляции . Все это изменилось с принятием переменных constexpr в C++ 11, которые расширили прямую и эффективную поддержку для констант пользовательских типов. Теперь программисты делают константы (типов классов) все более очевидными в программах. Так вырастают путаницы и фрустрации, связанные с обходными решениями .
...
Основные проблемы, связанные с "статический член данных" являются:
• они требуют "дублировать" заявления: один раз внутри шаблона класса , один раз за пределами класса, чтобы обеспечить «реальное» определение в случае использования констант.
• Программисты оба смягчены и запутаны необходимостью предоставления в два раза того же . Напротив, для «обычных» константных объявлений не требуется дубликатов деклараций.
...
Хорошо известные примеры в этой категории, вероятно, статический член функции numeric_limits или функции, такие как boost::constants::pi<T>()
и т.д. Constexpr функции шаблонов не страдают " дублирование деклараций "вопрос о том, что статические члены данных имеют; кроме того, они обеспечивают функциональную абстракцию. Тем не менее, они заставляют программиста заранее выбирать на сайте определения, как константы должны быть доставлены: либо по заданию const, либо по простым ссылочным типам.Если доставляется константой, то константы должны систематически выделяться в статическом хранилище; если не ссылочным типом, то константы нуждаются в копировании. Копирование не является проблемой для встроенных типов, но это showstopper для пользовательских типов со смысловой семантикой, которые не являются только обертки вокруг крошечных встроенных типов (например, матрица или целое число или bigfloat и т. Д.). контраст, «обычные» константы (expr) не страдают от этой проблемы . Дается простое определение, а решение состоит в том, должны ли константы на самом деле нуждаться в компоновке только в хранилище зависит от использования, а не от определения.
Предложение [N3651] (http://isocpp.org/files/papers/N3651.pdf), по-видимому, охватывает много этой информации. –