4

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)?

0

2 Answers 2

4

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>
Sign up to request clarification or add additional context in comments.

2 Comments

I think it works in C++11 as well (tried on both Clang and GCC).
@REACHUS: Thanks, tried it myself in gcc also and it worked - updated my answer.
1

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

3 Comments

The point of the question is "how do I make n[i] constant". The answer "you need to make n[i] constant" is therefore not useful.
@LightnessRacesinOrbit Ow. I'm sorry you didn't like the answer. :(
This is a nicer way to do the for loop!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.