2011-06-02 20 views
7

I N değerine bağlı olarak, farklı verir (bu durumda operatör(),) bir yöntem ile, bir şablonu sınıf D<N> oluşturma (uzman işlevi farklı dönüş türleri sahip olduğunda)Kod çoğaltma ve şablon uzmanlık

sadece iki ayrı sınıf bildirimleri oluşturarak bu işi yapabilir, ancak bu kod tekrarına bir sürü pahasına geldi. Ben de içine ortak şeyler atmak için ortak bir temel sınıf yaratıp çalıştım ama ...

#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; 
} 

Nasıl yapıcı doğru devralmak için alamadım ve ne kadar deyimsel yanı olacağını bilmiyorum Kodumu daha iyi görüntüleyebilir miyim?

+0

. Ya tutarlı bir polimorfik dönüş tipi yapın ya da her zaman temel bir tür döndürmek için mantıklı bir yol belirleyin. Böyle durumlarda genellikle uygulamanın temel ihtiyaçlarına geri dönmeyi faydalı buluyorum. – wallyk

+0

Sorun, belirli bir uzunluktaki listeleri kodlamak için iyi bir tür olmamasıdır. Şablon kara büyüsünü yapmak, küçük DSL'imin kullanımı ve tip güvenliğini sağlamak için güzel olmasını sağlar. – hugomg

+0

Yani bazı "derleme süresi uzunluğu" bağlantılı listesine ihtiyacınız var? Std :: array/boost :: dizisi sizin durumunuza uygun değil mi? Dezavantajı bir "subarray" nesnesini alamazsınız, ancak "çalışma zamanı değişken uzunluk arabirimini" de kullanabilirsiniz (yineleyiciler, [], işaretçi…). – ysdx

cevap

8

Merakla Yinelenen Şablon Kalıbı'nı kullanabilirsiniz.

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; 
    } 
}; 

Bu özel nesne şablon olma faydayı veya amaca uygun bkz O değil, kolayca olamazdı.

+0

+1 "Bu özel nesnenin şablonunu veya amacını görmediğim için, kolayca ayarlanamaz." – fedvasu

4

Daha iyi bakıyor emin değilim: ancak kaynak kod tekrarını önler: Sen parametrelerin değerine bağımlı olma dönüş türü yararını gözden geçirmek gerekir

// 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)); 
    } 
};