Дублирование кода и специализация шаблонов (когда специализированная функция имеет разные типы возврата) - PullRequest
7 голосов
/ 03 июня 2011

Я создаю шаблонный класс D<N> с методом (в данном случае оператором ()), который возвращает разные типы, в зависимости от значения N.

Я мог бы сделать эту работу толькосоздание двух отдельных объявлений классов, но это стоило большого количества дублирования кода.Я также пытался создать общий базовый класс, в который можно было бы добавить общие вещи, но я не мог заставить конструктор наследовать правильно и не знал, насколько это было бы идиоматично ...

#include <cstdio>

template <int N>
struct D{
    int s;
    D(int x):s(x){}

    int yell(int x){
        printf("N=%d, %d\n", N, s+x);
        return s+x;
    }

    D<N-1> operator()(int x){
        D<N-1> d(yell(x));
        return d;
    }
};

template <>
struct D<1>{
    int s;
    D(int x): s(x){}

    int yell(int x){
        printf("N=%d, %d\n", 1, s+x);
        return s+x;
    }

    int operator()(int x){
        return yell(x);
    }
};


int main()
{
    D<2> f(42);
    printf("%d\n", f(1)(2));
    return 0;
}

Как я могу сделать мой код лучше выглядящим?

Ответы [ 2 ]

8 голосов
/ 03 июня 2011

Вы можете использовать шаблон любопытно повторяющегося шаблона.

template<int N, template<int> typename D> struct d_inner {
    D<N-1> operator()(int x) {
        return D<N-1>(static_cast<D<N>*>(this)->yell(x));
    }
};
template<template<int> typename D> struct d_inner<1, D> {
    int operator()(int x) {
        return static_cast<D<1>*>(this)->yell(x);
    }
};

template <int N> struct D : public d_inner<N, D> {
    int s;
    D(int x):s(x){}

    int yell(int x){
        printf("N=%d, %d\n", N, s+x);
        return s+x;
    }
};

Не то, чтобы я видел полезность или цель этого конкретного объекта в качестве шаблона, это легко не могло быть.

4 голосов
/ 03 июня 2011

Я не уверен, что это выглядит лучше, но это позволяет избежать дублирования исходного кода:

 // Find a name for this ...
template<int N, template<int M> class X>
struct foo {
  typedef X<N> type;
};
template< template<int M> class X >
struct foo<0,X> {
  typedef int type;
};

template <int N>
struct D{
  int s;
  D(int x):s(x){}

  int yell(int x){
    printf("N=%d, %d\n", N, s+x);
        return s+x;
  }

  typename foo<N-1,D>::type
  operator()(int x){
    return typename foo<N-1,D>::type(yell(x));
  }
};
...