c++c++11templatestemplate-function

Template function dependent on non-type parameter


Is it somehow possible to define an overloaded template function based on a non-type parameter?

following situation:

template<uint8_t> void SetupMem();

template<> void SetupMem<4>()
{ /* some code */ }


template<> void SetupMem<8>()
{ /* some code */ }

void TemplateCaller()
{
   // use the plattform-specific template function at compile-time
   SetupMem<sizeof(size_t)>();
}

now is it somehow possible to change the return value of SetupMem based on the non-type parameter? e.g.:

template<> uint32_t SetupMem<4>(){}
template<> uint64_t SetupMem<8>(){}

So that TemplateCaller() does not explicitly calls SetupMem with the desired template parameter (so avoiding something like: SetupMem<uint64, sizeof(size_t)>();)? Possible solutions upto C++11 are welcome :)


Solution

  • Just use simple function overloading and std::integral_constant:

    std::uint32_t SetupMem(std::integral_constant<int, 4>); // (0)
    std::uint64_t SetupMem(std::integral_constant<int, 8>); // (1)
    
    void TemplateCaller()
    {
       auto a = SetupMem(std::integral_constant<int, 4>{}); // calls (0)
       auto b = SetupMem(std::integral_constant<int, 8>{}); // calls (1)
    }
    

    You can introduce a template type alias for readability:

    template <int X>
    using ic = std::integral_constant<int, X>;
    
    std::uint32_t SetupMem(ic<4>);
    std::uint64_t SetupMem(ic<8>);
    
    void TemplateCaller()
    {
       auto a = SetupMem(ic<4>{});
       auto b = SetupMem(ic<8>{});
    }
    

    live example on wandbox.org


    If your compiler doesn't support integral_constant, all you need to do is define it yourself:

    template <int>
    struct ic { };
    
    std::uint32_t SetupMem(ic<4>);
    std::uint64_t SetupMem(ic<8>);
    
    void TemplateCaller()
    {
       auto a = SetupMem(ic<4>{});
       auto b = SetupMem(ic<8>{});
    }
    

    live example on wandbox.org