2017-08-21 15 views
8

adında bir tür yok. Genel bir tek bağımsız değişkenli bir functor için Curiously Recurring Template Pattern ile denemeler yapıyorum ve iki uygulama var: bir şablon şablon parametresi kullanarak çalışır ve bir yere erişmeye çalıştığım bir saniye arayüz sınıfında türetilmiş Functor :: type. İkinci örnekte, derleyici (gcc 5.4.0)CTRP türetilmiş sınıf

hatası bildiriyor: hayır tip

template<class T, template<class> class Functor> 
class FunctorInterface_1 { 
private: 
    const Functor<T> &f_cref; 
public: 
    FunctorInterface_1() : f_cref(static_cast<const Functor<T>&>(*this)) {} 
    T operator() (T val) const { return f_cref(val); } 
}; // FunctorInterface_1 (works) 

template<class Functor> 
class FunctorInterface_2 { 
private: 
    const Functor &f_cref; 
public: 
    using Ftype = typename Functor::type; 
    FunctorInterface_2() : f_cref(static_cast<const Functor&>(*this)) {} 
    Ftype operator() (Ftype val) const { return f_cref(val); } 
}; // FunctorInterface_2 (no type in Functor!) 

I '< çift> struct Cube' in 'tip' adlı Daha sonra, aşağıdaki iki sınıfın) (ana çift T = derleme deneyin:

template<class T> 
struct Square : public FunctorInterface_1<T,Square> { 
    T operator()(T val) const { return val*val; } 
}; // Square 


template<class T> 
struct Cube : public FunctorInterface_2<Cube<T>> { 
    using type = T; 
    T operator() (T val) const { return val*val*val; } 
}; // Cube 

FunctorInterface_2/Cube örneği çalışacak şekilde değiştirilebiliyor veya , arabirim sınıfının ilk örnekte olarak T üzerinde tempillenmesi gerekli midir? Teşekkürler!

DÜZENLEME: gcc -std = C++ 14 kullanarak, ikinci bağımsız örnek ve otomatik çevirme olarak FunctorInterface_1 :: operator(), otomatik dönüş ve bağımsız değişken türleri kullanarak derlemek ve çalıştırmak için alabilirsiniz Tipler C++ 14 standardının bir parçası değildir.

DÜZEN 2: Biraz kalın hissediyorum. Yeni bir parametrede FunctorInterface_1 :: operator() şablonunu hazırlayabildiğimi fark ettim, ancak akılda tuttuğum uygulama için, temel sınıfımın türetilmiş sınıfta tanımlanan türlere erişmesini gerçekten istiyorum.

cevap

4

, Functor tanımı mevcut değildir. Bu nedenle, Functor::type kullanamazsınız.

Bu sınırlamayı aşmanın bir yolu, bir özellik sınıfı tanımlamaktır.

// Declare a traits class. 
template <typename T> struct FunctorTraits; 

template<class Functor> 
class FunctorInterface_2 { 
    private: 
     const Functor &f_cref; 
    public: 

     // Use the traits class to define Ftype 
     using Ftype = typename FunctorTraits<Functor>::type; 

     FunctorInterface_2() : f_cref(static_cast<const Functor&>(*this)) {} 
     Ftype operator() (Ftype val) const { return f_cref(val); } 
}; // FunctorInterface_2 (no type in Functor!) 

// Forward declare Cube to specialize FunctorTraits 
template<class T> struct Cube; 

// Specialize FunctorTraits for Cube 
template <typename T> struct FunctorTraits<Cube<T>> 
{ 
    using type = T; 
}; 

template<class T> 
struct Cube : public FunctorInterface_2<Cube<T>> { 
    using type = T; 
    T operator() (T val) const { return val*val*val; } 
}; // Cube 

Çalışma kodu: https://ideone.com/C1L4YW Sen Cube<T>FunctionInterface_2<Cube<T>> örneğini zaman ilk örneği alır anlamak zorunda

+0

Bu, bu türün ilk uygulamasında OP'nin yaptığı gibi şablon parametresi olarak doğrudan temini için oldukça şık bir alternatiftir. Ve şunu belirtmeliyim ki, eğer tür bir özellik olsa da, türetilmiş sınıf, onu da özellikten ayıklamak zorundadır. Bu, 'type type = T;' type = FunctorTraits > :: type; 'türünde olmalıdır. Aksi takdirde böyle bir uygulama gerçekten kırılgandır. – VTT

+0

Özellikler yaklaşımının arayüzlerimi agnostik tutmak için bazı çekiciliği vardır, ancak, türetilen türlere yük getirecek gibi görünmektedir. Akılda tuttuğum uygulama, indeksleme için bazı OrdinalType ve içerdiği veriler için bazı ElementType'a sahip olan soyut vektörler üzerinde karmaşık işlemleri içerir. Aynı zamanda, saf kalıtım yaklaşımını (mirastan ziyade) araştırıyorum, fakat şu anda uygulamış olduğumuz sanal mirasa (copius dinamik aşağı akış!) Yaklaşımı alternatiflerini araştırıyorum. –

+0

@ VTT, özellik yaklaşımının başka faydaları vardır. Örneğin. OP tarafından kullanılan ilk yaklaşımda olduğu gibi Functor sınıfının bir sınıf şablonu olması zorunlu değildir. İkinci noktaya katılıyorum. Ancak OP'nin buna hiç ihtiyacı olmayabilir. –

2

Kodunuz

template<typename TDerived> class 
Base 
{ 
    using Ftype = typename TDerived::type; 
}; 

template<typename T> class 
Derived: public Base<Derived<T>> 
{ 
    using type = T; 
}; 

Derived<int> wat; 

Çünkü Base örnekleme Derived sınıfın noktada çalışmıyor basitleştirilmiş olabilir tam değildir ve derleyici henüz Derived::type varlığından haberdar değildir. hat

using Ftype = typename Functor::type; 

temel sınıf işlendiğinde

1

. Bu, bu gerçekleşirken Cube<T> eksik bir tür olduğu anlamına gelir.
Bu nedenle derleyici Ftype = typename Functor::type;Functor kullanarak satırı aldığında eksiktir ve iç içe türlerinden herhangi birine erişemezsiniz.Eğer nokta FunctionInterface_2 ve Cube tam örneği olan hangi FunctionInterface_2 den operator() çağırana kadar Yani şimdi yaklaşık Functor gecikir bilgilere erişmesini

template<class Functor> 
class FunctorInterface_2 { 
private: 
    const Functor &f_cref; 
public: 
    FunctorInterface_2() : f_cref(static_cast<const Functor&>(*this)) {} 
    template <class TT> 
    auto operator() (TT && val) -> decltype(f_cref(val)) const { return f_cref(val); } 
}; 

: Senin durumunda

size FunctionInterface_2 değiştirebilir.

İlgili konular