2017-04-21 47 views
1

比方說,我有以下結構:模板多態性派生類的大小沒有新成員

template <typename T> 
struct Wrapper { 
    virtual T* get() const = 0; 
protected: 
    void *c_; 
}; 

template <typename C, typename T> 
struct WrapperOf: Wrapper<T> { 

    WrapperOf(C *c = 0) : c_(c) { } 

    virtual T* get() const { 
     C *c = static_cast<C*>(c_); 
     return static_cast<T*>(c->get()); 
    } 
}; 

它是由標準的保證,任何WrapperOf的大小將是相同的?通常情況下,我可以做到以下幾點:

struct Dummy { void* get(); }; 
struct Real { int* get(); }; 

char storage[sizeof(WrapperOf<Dummy, void>)]; 
Wrapper<int> *wp = 
    new(storage) WrapperOf<Real, int>(); 

如果我專注WrapperOf,通常爲:

template <> 
struct WrapperOf<void, void>: Wrapper<void> { 
    virtual void* get() const { return 0; } 
}; 

用它來初始化存儲(以避免一個Dummy類):

char storage[sizeof(WrapperOf<void, void>)]; 

這仍然有效嗎?

+0

所以你問如果sizeof(WrapperOf )== sizeof(WrapperOf )'? – NathanOliver

+0

@NathanOliver以及與'char []'相同的對齊方式...... –

+0

@NathanOliver是,正好 - 或者至少如果sizeof(WrapperOf )== sizeof(WrapperOf )''。 – Holt

回答

0

不,它在任何地方都沒有標準保證,因爲除了一些狹窄的情況外,標準沒有真正保證對象的大小。

值得注意的是,Standard並沒有提到有關虛擬函數實現的任何內容(像vptr這樣的東西在標準中不存在)。

0

有關尺寸保證的唯一類型是標準佈局類型。多態(除其他外)特別排除這一點。

然而,你可以做你想做的(我假設你要分配足夠的空間來創建任何類型的一組WrapperOf年代的):

#include <memory> 
#include <tuple> 

struct Dummy { void* get(); }; 
struct Real { int* get(); }; 
struct UnReal { float* get(); }; 

template <typename T> 
struct Wrapper { 
    Wrapper(void* c) : c_(c) {} 
    virtual T* get() const = 0; 
    void* get_c() { return c_; } 
    void* get_c() const { return c_; } 
protected: 
    void *c_; 
}; 


template <typename C, typename T> 
struct WrapperOf: Wrapper<T> { 

    WrapperOf(C *c = 0) : Wrapper<T>(c) { } 

    virtual T* get() const { 
     C *c = static_cast<C*>(this->get_c()); 
     return static_cast<T*>(c->get()); 
    } 
}; 

template <> 
struct WrapperOf<void, void>: Wrapper<void> { 
    virtual void* get() const { return 0; } 
}; 

template<class Type, class...Rest> 
struct largest_of 
{ 
    static constexpr auto x = sizeof(Type); 
    static constexpr auto y = largest_of<Rest...>::size; 
    static constexpr std::size_t size = x > y ? x : y; 

    static constexpr auto q = alignof(Type); 
    static constexpr auto p = largest_of<Rest...>::alignment; 
    static constexpr std::size_t alignment = q > p ? q : p; 
}; 

template<class T> struct largest_of<T> 
{ 
    static constexpr std::size_t size = sizeof(T); 
    static constexpr std::size_t alignment = alignof(T); 
}; 

template<class...Ts> struct largest_of<std::tuple<Ts...>> { 
    static constexpr std::size_t size = largest_of<Ts...>::size; 
    static constexpr std::size_t alignment =largest_of<Ts...>::alignment; 
}; 

using candidates = std::tuple< 
    WrapperOf<Real, int>, 
    WrapperOf<UnReal, float>, 
    WrapperOf<Dummy, void>, 
    WrapperOf<void, void> 
>; 

using largest = largest_of<candidates>; 
std::aligned_storage<largest::size, largest::alignment> storage; 

int main() 
{ 
    auto p1 = new (std::addressof(storage)) WrapperOf<Real,int>(); 
    p1->~WrapperOf<Real,int>(); 

    auto p2 = new (std::addressof(storage)) WrapperOf<UnReal, float>(); 
    p2->~WrapperOf<UnReal,float>(); 
} 
0

從目前的工作草案N4640(2017-02 -06)

5.3.3的sizeof [expr.sizeof]

  1. sizeof運算符產生其操作數的對象表示形式中的字節數。

  2. ...當將 應用於某個類時,結果爲該類的對象中的字節數,包括將該類型的對象放入數組所需的任何填充。

所以沒有任何事情擔保,只是它需要這麼多字節,因爲它需要。

即使是最基本的類型,標準說,這是實現定義

  1. ...的sizeof(炭),的sizeof(符號字符)和sizeof(無符號字符)爲1。適用於任何其他基本類型(3.9.1)的sizeof的結果是實現定義的。

人們可以推斷,它需要N個字節爲一些類和經驗看這是在給定實現的範圍內的派生類的相同。沒有保證。