简体   繁体   中英

Define constant array to use as template parameters

I am looking for a definition of constants (n) allowing them to be used as parameter in a template constructor, eg. something like this:

const int n[5] = { 4, 8, 16, 32, 64 };

for (int i = 0; i < 5; i++)
{
  SomeClass<n[i]> C;
  (...other things depending on n[i])
}

SomeClass looks like

template<int n> class SomeClass {...}

Is there any way to this (using macros or anything else)?

Yes, you can do this by using recursive templates to do the looping and specifying n as a constexpr . This will only work in C++11 or greater. Working example ( ideone link ):

#include <type_traits>

template <int n> 
class SomeClass 
{
// debug function for example
public:
    void debug() {
        cout << "SomeClass<" << n << ">" << endl;
    }
};

constexpr int n[5] = { 4, 8, 16, 32, 64 };

template <int i>
struct loop
{
    static void doit()
    {
        SomeClass<n[i]> C;
        C.debug();
        // other things depending on n[i]
        loop<i+1>::doit();
    }
};

// close out the iteration
template <> 
struct loop<std::extent<decltype(n)>::value>
{    
    static void doit() 
    {
    } 
};

int main() {
    loop<0>::doit();
    return 0;
}

Output:

SomeClass<4>
SomeClass<8>
SomeClass<16>
SomeClass<32>
SomeClass<64>

It's not possible with that for loop. The reason is simple: n[i] inside the loop is not a constant expression. i could change inside the loop in different ways and the information about whether to instantiate a specific instance of SomeClass or some other is runtime-dependent.

You can use template meta programming instead:

template <int from, int to>
struct for_ {
    template<template<int> class Fn>
    static void run() {
        Fn<from>::run();
        for_<from + 1, to>::template run<Fn>();
    }
};

template <int to> 
struct for_<to, to> {  
    template<template<int> class Fn>
    static void run() {} 
};

We can then define our own utilities:

template <int n> 
struct SomeClass {};

constexpr int n[5] = { 4, 8, 16, 32, 64 };

template<int i>
struct functor {
    static void run() {
        SomeClass<n[i]> c;
        // something else
    }
};

and use it as:

int main() {
    for_<0, 5>::run<functor>();
    return 0;
}

Live demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM