#c #templates #double #template-meta-programming #c 03
#c #шаблоны #двойной #шаблон-метапрограммирование #c 03
Вопрос:
Я пытаюсь создать метод, который, учитывая целочисленный ввод, выполняет некоторые вычисления (просто умножение и деление), возвращая результат в виде double
. Этот метод должен выполнять вычисления во время компиляции.
Я пробовал разные подходы, подобные этому:
template <int n> struct Try
{
static const double result = 1.0 / (double)n * Try<1>::resu<
};
template <> struct Try<1>
{
static const double result = 1.0;
};
Но по-прежнему безуспешно, я всегда получаю ошибки во время компиляции.
Редактировать: я не использую C 11
Комментарии:
1. Заменить
const
наconstexpr
.2. Спасибо.. Я забыл написать, что я не использую C 11, так что это не применимо
3. может быть, достаточно просто объявить статический const double result = myexpression 😀 но проблема остается.. как я могу вернуть double, используя методы метапрограммирования шаблонов?
4. В вашем коде нет «методов». На самом деле, в C нет «методов» (только функции-члены, но в вашем коде их по-прежнему нет). Вы действительно должны использовать C 11 для всего, что связано с метапрограммированием, это гораздо более подходящее.
5. вы правы.. кстати, чистый педантизм 😉
Ответ №1:
Заслуга принадлежит @ForEveR, я только что исправил небольшую ошибку в его ответе. Обратите внимание, что ничто не гарантирует, что вычисление действительно происходит во время компиляции. На самом деле ничто не гарантирует, что есть время компиляции. Бесстыдно скопированный ответ ниже.
Вы не можете инициализировать переменные нецелого типа в классе с const
помощью , вы можете сделать это только с constexpr
помощью . Поскольку вы не можете использовать C 11, вы можете попробовать это
template <int n> struct Try;
template <> struct Try<1>
{
static const double resu<
};
template <> const double Try<1>::result = 1.0;
template<int n> struct Try
{
static const double resu<
};
template<int n>
const double Try<n>::result = 1.0 / (double)n * Try<1>::resu<
Комментарии:
1. Привет, n.m, к сожалению, проблемы также здесь: ошибка: заголовок шаблона не разрешен в определении члена явно специализированного класса
2. Очень, очень странно.. может быть, это зависит от моей версии GCC
Ответ №2:
Чтобы сделать то, что вы хотите, вы можете использовать другую константу, которая поможет вам вычислить результат
Вот функциональный пример.
#include <iostream>
template <int n> struct Try;
template<int n> struct Try
{
static const double resu<
static const double _tmp;
};
template<int n>
const double Try<n>::_tmp = n*2; // another usefull operation because it's useless here
template<int n>
const double Try<n>::result = 1.0 / ((double)n * Try<n>::_tmp);
int main() {
std::cout << Try<5>::result << std::endl;
}
Комментарии:
1. Привет, Винк, спасибо за твой ответ.. ахах насчет этого комментария.. в любом случае, кажется, что это не работает: (.rodata 0x0):-1: ошибка: множественное определение `Try<1>::результат’
2. @user3770392 какой компилятор вы используете? Это должно сработать, хотя я не понимаю необходимости
tmp
, простого перемещения инициализации из области структуры должно быть достаточно само по себе.3. Я использую g 4.7.2 20130108, я собираюсь еще раз проверить, все ли в порядке .. Редактировать: просто проверил еще раз, все должно быть в порядке, но это не так
4. Странно, что вы получаете ошибку компиляции, потому что я использовал стандартную версию g , использующую gcc версии 4.6.3 (Ubuntu / Linaro 4.6.3-1ubuntu5)
5. да.. Я также удалил переменную _tmp, но все равно получаю ту же ошибку.. классические проблемы с шаблонами…
Ответ №3:
Ваш вопрос не очень ясен, но мне кажется, что вы хотите, чтобы во время компиляции оценка дроби превращалась в двойное число с плавающей запятой. Это можно сделать с помощью очень простой шаблонной функции. Этот рабочий пример создает двойники в разделе .rodata (протестировано с помощью gcc 4.8.2 и clang 3.4):
#include <iostream>
template<int N, int M> inline const doubleamp; Frac() {
static const double result = (double)N/M;
return resu<
}
int main() {
std::cout << Frac<3, 4>() << std::endl; // prints "0.75"
}