2
#include <iostream>
#include <tuple>
#include <utility>

template <typename... T>
decltype(auto) getParameterPackVals(T&&... Args) noexcept {
    return std::get<1>(std::forward_as_tuple(std::forward<T>(Args)...));
}

int main() {
    std::cout << getParameterPackVals(2, 1.0, 2.0, 3.0, 4.0, 5.0) << std::endl;
    //print(1.0, "Hello", "This", "is", "An", "Honour");
    return 0;
}

This is my current code that works, with using 1 as a place holder for the variable. Although when I replace 1 with a variable (I tried both size_t and int in the arguments for getParameterPackVals) it does not work.

template <size_t V, typename... T>
decltype(auto) getParameterPackVals(V n, T&&... Args){
    return std::get<n>(std::forward_as_tuple(std::forward<T>(Args)...));
}

Is this a gap in my understanding of how the std::get function works? Is there a way to make this work as is or would I need to write an entirely new function?

Evg
  • 25,259
  • 5
  • 41
  • 83
  • 1
    `std::get` expects an index that is known at compile time. Function parameters are never constexpr and can't be used where constant expressions are expected. – Evg Feb 23 '21 at 20:22

1 Answers1

2

Wow this is a first I solved it on my own!

So while brainstorming I remembered that if I named a template argument such as size_t V I could pass it in with <V> when I called the argument. So I took V n out of the function arguments and called the function as getParameterPackVals<2>(1.0, 2.0, 3.0, 4.0, 5.0). The final code is now:

#include <iostream>
#include <tuple>
#include <utility>

template <size_t V, typename... T>
decltype(auto) getParameterPackVals(T&&... Args) noexcept{
    return std::get<V>(std::forward_as_tuple(std::forward<T>(Args)...));
}


int main() {
    std::cout << getParameterPackVals<2>(1.0, 2.0, 3.0, 4.0, 5.0) << std::endl;
    return 0;
}

I'll leave the question up incase anyone else comes upon a similar problem.

  • 2
    Note that your function returns `double&&`, not `double`. There is a high risk of getting a dangling reference. – Evg Feb 23 '21 at 19:23
  • Yes I noticed while testing, luckily this was kind of just a little exercise to help me better understand parameter packs and the forward function. Do you have any suggestions to avoid the possibility of dangling references? – CrypticEthos Feb 23 '21 at 19:39
  • I'm not at my computer to test but would removing the && and allowing lvalues and rvalues be a valid solution. As I don't really care about only accepting rvalues, the && was once again kinda just practicing what I've been learning, I don't think the omission of && would cause problems with the forwarding? Unless I'm wrong – CrypticEthos Feb 23 '21 at 19:42
  • 1
    I for one think your code is correct as it is, you've implemented perfect forwarding correctly. It's no more dangerous than the built-in `? :`. – HolyBlackCat Feb 23 '21 at 19:48
  • 1
    You could replace `decltype(auto)` with `std::tuple_element_t>`. If the idea was to make a perfect forwarding function and you deliberately wanted to return `T&&` instead of `T`, then this change is not needed and @HolyBlackCat is right. – Evg Feb 23 '21 at 20:17