C++ 代码复制和模板专门化(当专门化函数具有不同的返回类型时)

C++ 代码复制和模板专门化(当专门化函数具有不同的返回类型时),c++,templates,template-specialization,C++,Templates,Template Specialization,我正在创建一个模板类D,其中包含一个方法(在本例中为操作符()),该方法根据N的值返回不同的类型 我只能通过创建两个独立的类声明来实现这一点,但这是以大量代码重复为代价的。我还试图创建一个公共基类来将公共内容放入其中,但我无法让构造函数正确继承,也不知道这会有多习惯 #include <cstdio> template <int N> struct D{ int s; D(int x):s(x){} int yell(int x){

我正在创建一个模板类
D
,其中包含一个方法(在本例中为操作符()),该方法根据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;
}
#包括
模板
结构D{
int-s;
D(intx):s(x){}
int-yell(int-x){
printf(“N=%d,%d\N”,N,s+x);
返回s+x;
}
D运算符()(int x){
D(yell(x));
返回d;
}
};
模板
结构D{
int-s;
D(intx):s(x){}
int-yell(int-x){
printf(“N=%d,%d\N”,1,s+x);
返回s+x;
}
int运算符()(int x){
回叫(x);
}
};
int main()
{
D f(42);
printf(“%d\n”,f(1)(2));
返回0;
}

如何使代码更美观?

您可以使用奇怪的重复模板模式

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;
    }
};
模板结构d\u内部{
D运算符()(int x){
返回D(静态施法(this)->yell(x));
}
};
模板结构d_内部{
int运算符()(int x){
返回static_cast(this)->yell(x);
}
};
模板结构D:公共D_内部{
int-s;
D(intx):s(x){}
int-yell(int-x){
printf(“N=%d,%d\N”,N,s+x);
返回s+x;
}
};

我并没有看到这个特定对象被模板化的实用性或目的,它可能很难做到。

我不确定它是否更好看:但它避免了源代码重复:

 // 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));
  }
};
//查找此文件的名称。。。
模板
结构foo{
类型def X类型;
};
模板<模板类X>
结构foo{
typedef int类型;
};
模板
结构D{
int-s;
D(intx):s(x){}
int-yell(int-x){
printf(“N=%d,%d\N”,N,s+x);
返回s+x;
}
typename foo::type
运算符()(int x){
返回typename foo::type(yell(x));
}
};

您需要重新考虑返回类型的实用性是否取决于参数的值。要么使其成为一致的多态返回类型,要么找出一种明智的方法始终返回基本类型。在这种情况下,我通常会发现返回到应用程序的基本需求是有帮助的,问题是没有一种好的类型来编码特定长度的列表。使用模板黑魔法可以让我的小DSL使用起来很好,并且类型安全。所以你需要一些“编译时长度”的链表吗?std::array/boost::array不适合您的情况吗?缺点是,您不能从中获取“子数组”对象,但也可以使用“运行时可变长度接口”(迭代器,[],指针…)。+1表示“我看不到模板化此特定对象的实用程序或目的,但很容易无法”