Arguments of a template inside compilation time deployed for a loop?

wikipedia ( here ) gives compilation time for a for loop ....... I was wondering if we can use similar ones for a loop with template operators inside ... for example ...

is the next cycle, valid

template<int max_subdomain> void Device<max_sudomain>::createSubDomains() { for(int i=0; i< max_subdomain; ++i) { SubDomain<i> tmp(member); ... // some operations on tmp ... } } 

SubDomain is a class that accepts an int template parameter and was created here with an argument that is a member of the Device class.

Thanks for the answer guys ... now that you know what I want ... is there anyway I achieve what I want?

I finally got what I wanted .............. instead of using the for loop directly ... you can use the Boost :: MPL for_each construct instead . I have not implemented it yet, but I assume that this makes it possible to do what I wanted .....

I took the answer from another question about stack overflow here ... However, a comment to the same question condemns its use, because it will be very slow (for large loops, of course) ... however .. for loops that are small, I don’t I think there should be some bloating ... I'll try the code and let the results know ....

usage is well illustrated in example

+6
source share
3 answers

Re-edit

My previous answer was correct. I tried your code giving a compiler error . You cannot declare such objects, since i cannot remain a compile-time constant (as you are going to do i++ ). The template parameter should always be compile time constants. Here is a demo .

Also note that loop unwrapping is performed for regular loops as well as part of the compiler optimization. It is not limited to template s.

0
source

There is a solution for this. Convert iteration to recursion.

 template<int i> void Device::createSubDomains() { SubDomain<i> tmp(member); // some operations on tmp createSubDomains<i-1>(); } template<> void Device<-1>::createSubDomains() { // End of recursion. } 

Note. You cannot use runtime if(i!=0) createSubDomains<i-1>(); .

2017 Note: now you can use compile time if constexpr(i!=0) createSubDomains<i-1>();

+7
source

Even if you already accepted @iammilind's answer, let me suggest one more, because his argument as to why i not a constant of the compile-time constant is not true.

Suppose you have

  template<unsigned int MAX> struct SubDomain {...}; ... 

and you want to declare an instance of it ...

  SubDomain<i> tmp(member); 

then i should usually be the so-called compile-time constant. What is it?


Pedantry

The standard assigns the term nontype template argument that are not types (D'Oh).

14.3.2 Non-type argument templates [temp.arg.nontype]

The template argument for a non-piggy template without template must be one of:
- integral constant expression of an integral or enumerated type; or
-... [further followed, but not relevant]

To the right, the first dot contains a link for further research: an integral constant-expression . It brings us to

5.19 Constant Expressions [expr.const]

In several places, C ++ requires expressions that calculate an integral or continuous constant: as an array (8.3.4, 5.3.4), as expressions in the case of (6.4.2), as the length of bit fields (9.6), as initializers of the enumerator (7.2), as initializers of static elements (9.4.2), and as integral or enumerated arguments of a non-piggy type template (14.3) .

Then the key:

An integral constant expression can include only literals (2.13), counters, constant variables or static data members of integral or enumerated types, initialized by constant expressions (8.5), a non-type type template, parameters of integral or enumerated types, and sizeof expressions.


Pedantry application

If we look back at your cycle:

 for (int i=... ... SubDomain<i> 

then now we can notice that i is not allowed there. What for? Since i NOT a const variable .

Now the observer might think that you can get around this:

 for (int i=... ... const int I = i; SubDomain<I> 

But is it really allowed? Negative, I = i not an integral constant expression, because i not. This helps to understand that the rule for integral constant expressions is applied recursively.

For example, suppose the following code:

 template <int> void foo() {} int main () { const int ccI = 0; const int ccJ = ccI*2; const int ccK = ccJ/4; foo<ccK>(); } 

But if only one part of the chain is made not const, then ccK no longer considered an integral constant:

 template <int> void foo() {} int main () { int ccI = 0; const int ccJ = ccI*2; // not compile time constant const int ccK = ccJ/4; // same foo<ccK>(); // error } 


Summary

Thus, in a human-readable form, template arguments that are not types but (integer) values ​​must be compilation constants:

  • The compile-time constant initializer should include only other compile-time constants
  • literal value - compile time constant
  • enum value is a compile time constant
  • Functional calls do not give compile-time constants (for some preliminary reasons)
+2
source

Source: https://habr.com/ru/post/893041/


All Articles