2

The following is the sample code, which cannot compile.

We use iteration function to iterate over some range and run the lambda callback function. The iterate function will pass some indications (i.e. type) to the callback lambda function, which will then do works based on indications. Since these indications are fixed in compile-time, I believe there is a way to remove all indication overhead in runtime. But how..?

template<typename FuncT>
void iterate(const FuncT& func) {
    for(int i = 0; i < 5; ++i)
        func(0, i);
    for(int i = 0; i < 5; ++i)
        func(1, i);
}

template<int d> int getValue(int i) { return d+i; }
// this has run-time overhead compared to the template version
// int getValue(int d, int i) {return d+i; }

int main() {
    iterate([&](const int type, int index){
        // error: cannot compiler here
        // candidate template ignored: invalid explicitly-specified argument for template parameter 'd'
        std::cout<<getValue<type>(index)<<std::endl;
    });
}
Yuwei XIAO
  • 43
  • 4
  • In `getValue(index)` the value of type must be known at compile time, but it is not known until the lambda is called at runtime. What exactly do you want to achieve? – Werner Henze May 14 '20 at 11:57
  • @WernerHenze you're right. it is just a sample code. In my project, the parameter passed to the lambda function (i.e. type) is known at compile time. I am just wondering is there a way to remove it from runtime through template. I guess Evg gives a very cool solution. – Yuwei XIAO May 14 '20 at 12:25

1 Answers1

1

You can't use a run-time variable as a template parameter, which should be a compile-time constant. But you can wrap constants into std::integral_constant to encode a constant value into a type:

template<typename Func>
void iterate(Func func) {
    for(int i = 0; i < 5; ++i)
        func(std::integral_constant<int, 0>{}, i);
    for(int i = 0; i < 5; ++i)
        func(std::integral_constant<int, 1>{}, i);
}

template<int d>
int getValue(int i) {
    return d + i;
}

int main() {
    iterate([&](auto type, int index) {
        std::cout << getValue<type>(index) << std::endl;
    });
}

std::integral_constant can be implicitly converted into a value of underlying type. In getValue<type>(index), type is converted into the wrapped value of type int.

Demo

Evg
  • 25,259
  • 5
  • 41
  • 83