LINUX.ORG.RU

non type templates с лишь одним фиксированым параметром шаблона

 ,


0

2

Почему такое не работает?

#include <cstdio>

template <int n, int a>
int fact()
{
  return fact <n-1, a*n> ();
}

template <>
int fact <1, int a> ()
{
  return a;
}

int main()
{
  printf("%d\n", fact <5, 1> ());
}

Можно конечно засунуть int a в параметры ф-ии, а не шаблона, но хочется знать, как сделать, что бы такое работало. В чисто образовательных целях.

Частичная специализация шаблонных функций запрещена. Почему — х.з. Возможно, какие-то непоправимые корчи в механизме разрешения перегруженных символов.

Manhunt ★★★★★
()

как сделать, что бы такое работало

Использовать шаблонные классы, а не шаблонные функции.

Manhunt ★★★★★
()

Сделай свою ф-цию членом шаблонного класса (и параметризуй его) и преобразуй оператором в вызов () :) (Чисто чтоб работало если)

slackwarrior ★★★★★
()

Шаблонные функции можно специализировать только полностью, так что не выделывайся, а пиши факториалы как все:

template <int i>
struct fact
{
    enum { value = i * fact<i - 1>::value };
};

template <>
struct fact<0>
{
    enum { value = 1 };
};
theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Ну если прям так хочешь с функцией:

template <int i>
constexpr int fact()
{
    return i * fact<i - 1>();
}

template <>
constexpr int fact<0>()
{
    return 1;
}
theNamelessOne ★★★★★
()

Ну или

template <int N>
struct Fib {
    static int const value = Fib<N-1>::value + Fib<N-2>::value;
    
};

template <>
struct Fib<1> {
    static int const value=1;
};

template <>
struct Fib<0> {
    static int const value=0;
};

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от slackwarrior

Так что ли? Так то же не компилируется.

#include <cstdio>

template <int n, int a>
class Fact
{
  public:
    int operator ()() {
      return Fact <n-1, a*n> ()();
    }
};

template <>
class Fact <1, int a>
{
  public:
    int operator ()() {
      return a;
    }
};

int main()
{
  printf("%d\n", Fact <5, 1> ()());
}
Чего-то голова не варит сегодня. Не выспался что-ли..

nanoolinux ★★★★
() автор топика
Ответ на: комментарий от theNamelessOne

можно специализировать только полностью

Да я уже как-то догадался. Но меня интересует как сделать факториал на шаблонах с аккумулятором?

nanoolinux ★★★★
() автор топика
Ответ на: комментарий от slackwarrior

template instantiation depth exceeds maximum of 900

зависит от компилятора, и установок, но можно менять, 900 это еще гуд, а то обычно 128б 500

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от nanoolinux

Но меня интересует как сделать факториал на шаблонах с аккумулятором?

Можно на структурах сделать:

#include <iostream>

template <int num, int acc>
struct fact_acc
{
    enum { value = fact_acc<num - 1, num * acc>::value };
};

template <int acc>
struct fact_acc<0, acc>
{
    enum { value = acc };
};

template <int num>
struct fact
{
    enum { value = fact_acc<num, 1>::value };
};

int main()
{
    std::cout << fact<5>::value << std::endl;
}
theNamelessOne ★★★★★
()
Ответ на: комментарий от slackwarrior

maximum of 900

А у меня 500 всего

>g++ --version
g++ (Ubuntu 4.4.6-3lucid2) 4.4.6
Да понятно, что ссзб. Это в образовательных целях =)

nanoolinux ★★★★
() автор топика
Ответ на: комментарий от nanoolinux

Так то же не компилируется.

#include <iostream>

template <int num, int acc>
struct fact
{
    static constexpr int value()
    {
        return fact<num - 1, num * acc>::value();
    }
};

template <int acc>
struct fact<0, acc>
{
    static constexpr int value()
    {
        return acc;
    }
};

int main()
{
    std::cout << fact<5, 1>::value() << std::endl;
}

Только этот пример ничем принципиально не отличается от моего предыдущего примера с структурой (кроме того, что появляется ненужный статический метод).

theNamelessOne ★★★★★
()
Ответ на: комментарий от nanoolinux

а так, - можешь проверить?

template <int N, int A=1>
struct Fib {
    static int const value = (Fib<N-1>::value * A) + (Fib<N-2>::value * A);
    
};

template <int A>
struct Fib<1, A> {
    static int const value=1 * A;
};

template <int A>
struct Fib<0, A> {
    static int const value=1 * A;
};
Подправил Т.е. так как-то

Boy_from_Jungle ★★★★
()
Последнее исправление: Boy_from_Jungle (всего исправлений: 1)
Ответ на: комментарий от nanoolinux

И обернуть вызов в оператор преобразования, если важна семантика вызова - все скомпилируется и будет работать :)

#include <iostream>

template <int num, int acc>
struct fact_acc
{
    enum { value = fact_acc<num - 1, num * acc>::value };
    
    int operator ()()
    {
      return value;
    }
    
};

template <int acc>
struct fact_acc<0, acc>
{
    enum { value = acc };
    
    int operator ()()
    {
      return value;
    }   
};

template <int num>
struct fact
{
    enum { value = fact_acc<num, 1>::value };
    
     int operator ()()
    {
      return value;
    }   
};

int main()
{
    std::cout << fact<5>::value << std::endl;
    std::cout << fact<5>()() << std::endl;   
}

Вот так, методом последовательных приближений буханка хлеба превраща брюки превраща... Ну ты понел? :)

slackwarrior ★★★★★
()
Ответ на: комментарий от theNamelessOne

Возможно, кого-то коробит :: :) Экономия буковок - это очень важно. Тут помнится многостраничные треды создавал какой-то фоннат сишных однострочников, вероятно с древним ЭЛТ монитором низкого разрешения.

slackwarrior ★★★★★
()
Ответ на: комментарий от slackwarrior

Ну ты понел?

Ну так, факториалы на темплейтах на спп, буханкотроллейбусотред!

nanoolinux ★★★★
() автор топика
Последнее исправление: nanoolinux (всего исправлений: 1)
Ответ на: комментарий от Boy_from_Jungle

а еще чо-то все завтыкали, нужно засунуть проверку для аккумулятора

static_assert(A>0,"A is small");

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от Manhunt

Возможно, какие-то непоправимые корчи в механизме разрешения перегруженных символов.

именно, данный механизм конфликтовал бы с механизмом перегрузки функций

DELIRIUM ☆☆☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.