2016-07-20 35 views
0

我有一個可變參數模板類「InterleavedAttribute」,現在我想要關於模板中的類型的一些運行時信息(「AttributeTypeInfo」)。我想在模板類(「attributeInfo」)中填充靜態常量數組,然後在運行時使用索引來訪問該數組,比如object.typeInfo(2),但我無法弄清楚。以下是我的:在variadic模板類中初始化靜態數組

#include <iostream> 

template <typename TYPE> struct GLTypeInfo; 

template <> 
struct GLTypeInfo<char> { static constexpr unsigned int glType = 0; }; 

template <> 
struct GLTypeInfo<int> { static constexpr unsigned int glType = 1; }; 

template <> 
struct GLTypeInfo<float> { static constexpr unsigned int glType = 2; }; 

//--------------------------------------------------------------------------- 

struct AttributeTypeInfo 
{ 
    unsigned int nrOfComponents; 
    unsigned int glType; 
    unsigned int bytesPerComponent; 
    unsigned int bytesPerAttribute; 

    constexpr AttributeTypeInfo(unsigned int _nrOfComponents, unsigned int _glType, unsigned int _bytesPerComponent, unsigned int _bytesPerAttribute) 
     : nrOfComponents(_nrOfComponents), glType(_glType), bytesPerComponent(_bytesPerComponent), bytesPerAttribute(_bytesPerAttribute) 
    {}  
}; 

template <typename T> 
struct TypeInfoFactory 
{ 
    static unsigned int constexpr extent = std::is_array<T>::value ? std::extent<T>::value : 1; 
    using type = typename std::conditional<std::is_array<T>::value, typename std::remove_extent<T>::type, T>::type; 
    static constexpr AttributeTypeInfo typeInfo = AttributeTypeInfo(extent, GLTypeInfo<type>::glType, sizeof(type), sizeof(type) * extent); 
}; 

//--------------------------------------------------------------------------- 

template <typename TYPE, typename ...P> struct InterleavedAttribute 
{ 
    static constexpr unsigned int nrOfAttributes = sizeof...(P)+1; 
    //static constexpr AttributeTypeInfo attributeInfo[sizeof...(P)+1] = { ??? }; // <-- How do I fill this... 
    TYPE data; 
    InterleavedAttribute<P...> next; 
    InterleavedAttribute() {} 
    InterleavedAttribute(const TYPE & value, const P &... p) : data(value), next(p...) {} 
    //static constexpr AttributeTypeInfo typeInfo(unsigned int index) { return attributeInfo[index]; } // ...so I can call this later? 
}; 

template <typename TYPE> struct InterleavedAttribute<TYPE> 
{ 
    static constexpr unsigned int nrOfAttributes = 1; 
    static constexpr AttributeTypeInfo attributeInfo[1] = { TypeInfoFactory<TYPE>::typeInfo }; 
    TYPE data; 
    InterleavedAttribute() {} 
    InterleavedAttribute(const TYPE & value) : data(value) {} 
    static constexpr AttributeTypeInfo typeInfo(unsigned int index) { return attributeInfo[0]; } 
}; 

int main() { 
    InterleavedAttribute<int> ia1(5); 
    std::cout << "Numer of attributes: " << ia1.nrOfAttributes << std::endl; 
    std::cout << "Attribute 0, glType: " << ia1.typeInfo(0).glType << std::endl; 

    InterleavedAttribute<float, int, char> ia3(1.2, 3, 'a'); 
    std::cout << "Numer of attributes: " << ia3.nrOfAttributes << std::endl; 
    //std::cout << "Attribute 0, glType: " << ia3.typeInfo(0).glType << std::endl; <-- Trying to get type information here 
} 

該代碼在Coliru here上。 我發現this答案,這是接近的,但我還是無法真正弄清楚如何得到我想要的東西......

回答

2

你可以做std::tuple如下:

template <typename ...Ts> struct InterleavedAttribute 
{ 
    static constexpr unsigned int nrOfAttributes = sizeof...(Ts); 
    static constexpr AttributeTypeInfo attributeInfo[sizeof...(Ts)] = { 
     TypeInfoFactory<Ts>::typeInfo... 
    }; 
    std::tuple<Ts...> data; 

    InterleavedAttribute() {} 
    InterleavedAttribute(const Ts&... args) : data(args...) {} 
    static constexpr AttributeTypeInfo typeInfo(unsigned int index) { 
     return attributeInfo[index]; 
    } 

    template <unsigned int I> 
    auto attribute() -> decltype(std::get<I>(data)) { return std::get<I>(data); } 
    template <unsigned int I> 
    auto attribute() const -> decltype(std::get<I>(data)) { return std::get<I>(data); } 
}; 

// odr-used, so definition required for linker. 
template <typename ...Ts> 
constexpr AttributeTypeInfo InterleavedAttribute<Ts...>::attributeInfo[sizeof...(Ts)]; 

Demo

+0

該死的。我太快了。我需要第一個TYPE模板參數來訪問數據。 這對我不起作用:ia3.typeInfo(i).glType。 新代碼是[這裏](http://coliru.stacked-crooked.com/a/216d4af2b5660024) – Bim

+0

謝謝,但是使用Boost。我只是試圖使用std lib。與此同時,我已經使用元組轉換你的代碼,以返回內部數據,[它更漂亮](http://coliru.stacked-crooked.com/a/0d972773b6a82ba8)。你能解釋爲什麼鏈接錯誤發生?我不知道... – Bim

+0

@Bim:更新了答案和演示。 – Jarod42