Search code examples
c++templatesgeneric-programming

Can I use template parameter as variable?


I want to allocate memory according to the template parameter like this:

enum typeFlag {
kFloat32 = 0,
kFloat64 = 1,
kFloat16 = 2,
kUint8 = 3,
kInt32 = 4,
kInt8  = 5,
kInt64 = 6,
kBool = 7,
kInt16 = 8
};

template<typename dtype, typename ctx>
inline TBlob<dtype,ctx>::TBlob(const size_t &size): shape_{size} {
    switch(dtype){
        case kFloat32:
            dptr_ = new float[size];
            break;
        case kFloat64:
            dptr_ = new double[size];
            break;
...

and the compiler throw an error like:

error: expected primary-expression before ‘)’ token
     switch(dtype){
                 ^

Can I achieve my goal while keeping the same meaning of dtype?


Solution

  • It seems you want to map a non-template (enumerator) parameter to a type:

    #include <cstddef>
    
    // Platform-independent type descriptions.
    enum class TypeFlag {
    kFloat32 = 0,
    kFloat64 = 1
        // ...
    };
    
    // Platform-specific TypeFlag to type mapping.
    template<TypeFlag FLAG>
    struct MappedType;
    
    // Specialize type mapping for the platform-independent
    // type representations (TypeFlag) that can be represented
    // on this particular platform.
    template<>
    struct MappedType<TypeFlag::kFloat32> { using type = float; };
    
    template<>
    struct MappedType<TypeFlag::kFloat64> { using type = double; };
    
    // ...
    
    template<TypeFlag FLAG>
    using MappedType_t = typename MappedType<FLAG>::type;
    
    template<TypeFlag FLAG, std::size_t SIZE>
    struct TBlob {
        using BlobType = MappedType_t<FLAG>;
    
        TBlob() {
            dptr_ = new BlobType[SIZE];
        }
    
        // ...
    
    private:
        BlobType* dptr_;
    };
    

    Note that double isn't necessarily a 64 bit float on all target architectures, so this approach is not necessarily portable, and would arguably go into a platform-specific type mapping.