2013-04-08 144 views
4

在C++ 11中,我希望只有在默認模板值被選中的情況下,才能在類和構造函數中使用其成員變量(僅適用於支持的類型,如int , 當然)。成員變量和構造函數依賴於模板參數

什麼是推薦的方法來實現這一點(允許提升)?

喜歡的東西:

template< int _x = -1 > struct C { 
    C() {} // only available if _x != -1 
    C(int x) : x(x) {} // only available if _x == -1 
    // more methods that are common for all _x and refer to _x/x 
    private: 
    int x; // only available if _x == -1 
    // more members that are common for all _x 
}; 

或者,以另一種方式:對於規模和速度優化,我想用一個編譯時間常數代替如果存儲在一個成員變量的值大於另一個值模板默認被選中。

-

這裏是做出了榜樣一切更加清晰:

template< int _size = -1 > struct Block { 
    Block() { buf = mmap(_size, ...); } // exists only when size!=-1 
    Block(int s) { buf = mmap(size = s, ...); } // exists only when size==-1 
    ~Block() { munmap(buf, getSize()); } // should use the correct size 
    int getSize() const { return ???; } // gets _size if !=-1, size otherwise 
    // other methods that use buf and getSize() 
    private: 
    void *buf; 
    const int size; // only exists for size == -1! 
}; 

這解決了它部分:

template< int _x > struct X { 
    int getX() const { return _x; } 
}; 
template<> struct X< -1 > { 
    X(x) : x(x) {} 
    int getX() const { return _x; } 
    private: 
    int x; 
}; 

template< int _x = -1 > struct C : X<_x> { 
    C() {} // only available if _x != -1 
    C(int x) : X<_x>(x) {} // only available if _x == -1 
    // more methods that are common for all _x and use this->getX() 
}; 

但是,我們的C的構造,以及其他的/更好的解決方案?

回答

4

,但也許它可以幫助:你可以嘗試使用一個基類只對細微差別和「假」的成員變量時,它的不存在允許其餘的編譯:

template< int _x > class B 
{ 
public: 
    B() {} 
protected: 
    static const int x = _x; 
}; 

template<> class B< -1 > 
{ 
public: 
    B(int i) : x(i) {} 
protected: 
    int x; 
}; 

template< int _x = -1 > 
class C : public B<_x> 
{ 
public: 
    using B<_x>::B; // inherit B's ctors 

    void f() 
    { 
    if (x == ...) // uses either the member variable x or the static const int x! 
    } 
}; 

但正如我所說,這只是一個想法...

+0

哦,那個'使用'技巧可能真的做到了,謝謝!有沒有其他的選擇,例如,如果我不僅有一個參數像'_x',而是'_x'和'_y'? – Thomas 2013-04-08 19:17:22

+0

@Thomas對'B'有三個專業?我知道,這並不是真正的擴展,但它取決於你的用例的很多細節......恐怕沒有我知道的簡單而通用的解決方案。 – 2013-04-08 19:22:55

+0

@Thomas我已將我的例子顛倒過來,請參閱經過編輯的答案! – 2013-04-08 19:28:16

2

專業化是要走的路:只是一個想法

template <int N> struct C 
{ 
    C(int n) : n_(n) { } 
    int n; 
}; 

template <> struct C<-1> 
{ 
    C() { } 
    C(int n) : n_(n) { } 
    int n; 
}; 
+0

想象一下,我的C(在這兩種情況下)都包含一些常見的其他成員和方法。然後,我可能會從您建議的專門類中派生出來,但我無法再訪問其構造函數。 – Thomas 2013-04-08 18:11:13

+0

(我相應地編輯了這個問題) – Thomas 2013-04-08 18:17:43

+2

@Thomas:反過來:讓模板從一個公共基類繼承。 – 2013-04-08 21:05:15

0

我Kerrek SB我就這一個。將通用代碼(即運行時緩衝區處理)放入公共基類中,創建兩個派生類,一個用於靜態大小的緩衝區類,另一個用於動態緩衝區類。或者更好的是,根據common coding guidelines,使用組合。

class buffer_impl { 
    public: 
     buffer_impl(int size) : data_ {mmap(size, ...)}, size_ {size} {} 
     ~buffer_impl() { munmap(data_, getSize()); } 
     int getSize() const noexcept { return size_; } 

     // other buffer routines 
     // ... 
    private: 
     void* data_; 
     int size_; 
    }; 

    template <int _size = -1 > 
    class buffer { // static size 
    public: 
     buffer() : impl_ {_size} {} 
     static constexpr int getSize() noexcept { return _size; } 
    private: 
     buffer_impl impl_; 
    }; 

    template <> 
    class buffer<-1> { // dynamic size 
    public: 
     buffer(int size) : impl_ {size} {} 
     int getSize() const noexcept { return impl_.getSize(); } 
    private: 
     buffer_impl impl_; 
    }; 
相關問題