2013-01-08 41 views
2

我可以有一個有或沒有基於模板的成員的類嗎?虛代碼:我可以自定義類是否具有基於模板參數的成員?

template <typename HasBazMember=true> 
class Foo { 
    int bar; 

    ConditionallyHaveMember<int, HasBazMember> baz; 
}; 

所以在上面我想讓Foo有會員「baz」和Foo沒有。

+2

如果您的解決方案有條件地擁有會員,您正在解決什麼問題? – GManNickG

+0

@GManNickG:我有一個類應該有一個緊湊的變化(更小的sizeof'),我研究可能性(使用繼承有其問題) – zaharpopov

回答

2

是的,你可以,但你必須專門化整個班級。例如:

template< bool HasBazMember = true > 
class Foo { 
    int bar; 
    int baz; 
}; 

template<> 
class Foo<false> { 
    int bar; 
}; 

如果可以分開的邏輯,你可以把這些成員在基類,這樣你就不用複製代碼整個類。例如,

template< bool HasBazMember > 
class FooBase 
{ 
protected: 
    int baz; 
}; 

template<> 
class FooBase<false> 
{ 
    // empty class 
    // the Empty Base Optimization will make this take no space when used as a base class 
}; 

template< bool HasBazMember = true > 
class Foo : FooBase<HasBazMember> 
{ 
    int bar; 
}; 

或者使用Boost.CompressedPair:在C++ 11

struct empty {}; 

template< bool HasBazMember = true > 
class Foo 
{ 
    boost::compressed_pair< 
     int 
     , typename std::conditional< HasBazMember, int, empty >::type 
    > bar_and_maybe_baz_too; 
}; 
+0

所以如果類有很多其他成員,我必須寫所有他們兩次? – zaharpopov

+0

@zaharpopov:不一定,您可以使用_helper基類class_或_compressed pair_。 –

+0

什麼是壓縮對? – zaharpopov

4

解決方案,而specialisazion:

class empty {}; 

template <typename T> 
struct wrap { T wrapped_member; }; 

template <bool HasBazMember=true> 
class Foo : private std::conditional<HasBazMember, wrap<int>, empty>::type { 
public: 
    int bar; 

    int& baz() { 
    static_assert(HasBazMember, "try using baz without HasBaz"); 
    return static_cast<wrap<int>&>(*this).wrapped_member; 
    } 
}; 


int main() 
{ 
    Foo<true> t; 
    t.baz() = 5; 

    Foo<false> f; 
    f.baz() = 5; // ERROR 
} 

指出,由於EBO,沒有空間的開銷,如果HasBazMember=false

相關問題