Is there any way to "capture" local scope template variables (akin to a lisp special) and use as default?

Viewed 55

In the following code:

#include <iostream>
#include <type_traits>

// this code below won't compile unless at this point there is already
// a typename rate
// using rate = std::integral_constant<int, 10>;

template<typename rate=rate> void functionA()
{
  static_assert(rate::value > 5);
  std::cout << "functionA: " << rate::value << std::endl;
}

template<typename rate> void loop()
{
    functionA<std::integral_constant<int, 50>>(); // => prints "functionA: 50"
    functionA();  // <- I would like this call to infer loop's functions's rate template type (which would be 20)
}

void other()
{
   using rate = std::integral_constant<int, 12>;
   functionA(); // => prints "functionA: 12"
}

void bare_loop()
{
   functionA(); // should give compile time-error: no 'rate' in semantic scope
}

int main() {

  loop<std::integral_constant<int, 20>>();
  
    return 0;
}

I would like to be able to write a templated function which has a default parameter value which remains undeclared until compilation is necessary.

The above shows the most minimal piece of code to express this idea.

What I'm trying to achieve is directly inspired by Lisp's variable capture mechanism (lexical and dynamic scope).

To be clear: this is entirely a compile-time problem and solution.

Is this possible in the current state of affaires of C++?

1 Answers

I am really not sure if I understood what you intended, but if you want is a function that could either take the parameter rate at compile time or at runtime, well, one possibility would be to use a default parameter in function "functionA", determined by the template parameter. So you can define the default in compile time, and override it in runtime if needed.

I leave an example below in case it helps, however I can't understand what it the desired use case, and it can be possibly a bad design:

#include <iostream>
#include <cassert>

constexpr int infer() { return 123; }

const int MIN_RATE_LIM = 5;
template<int t_rate=infer()> void functionA(const int rate = t_rate)
{
  assert(rate > MIN_RATE_LIM);
  std::cout << "functionA: " << rate << std::endl;
}

template<int rate> void loop()
{
  for(int i = 0; i < 10; i++ )
  {
    functionA<50>();
    functionA<rate>();
    functionA<rate>(12);  // <- 12 will overlap the value 10 in this line
  }
}

int main() {

  loop<10>();
  
    return 0;
}
Related