I have a Variadic Template function in C and I want to iterate over the template arguments and cherry-pick those arguments that are pointers.
PLEASE SEE THE UPDATE SECTION BELOW.
So, I have the following code below. I wrote a skeleton code that is compilable and runnable.
g -std=c 17 f3_stackoverflow.cpp && ./a.out
I am just curious about the part that says: LOGIC GOES HERE
#include <iostream>
#include <vector>
#include <utility>
template <typename... Args>
std::vector<std::pair<int, void*>> check(Args... args) {
std::vector<std::pair<int, void*>> ret;
// LOGIC GOES HERE
return ret;
}
void printVector(std::vector<std::pair<int, void*>> v) {
for(const auto& _v : v) {
std::cout << _v.first << " : " << _v.second << std::endl;
}
}
int main(int argc, char const *argv[])
{
int n = 100;
int a;
std::vector<int> b(n);
float c;
std::vector<float> d(n);
char e;
std::vector<char> f(n);
auto pairs = check(a, b.data(), c, d.data(), e, f.data());
printVector(pairs);
return 0;
}
So, I want to see the following output in the stdout
of the program:
1 : 0x123
3 : 0x567
5 : 0x980
UPDATE:
Basically, I am looking for the indexes where the argument is a pointer (e.g., int*
, float*
, ...) and the address the pointer is pointing to. That is why you see the output that I provided.
Explanation of the output: The second, fourth, and sixth arguments are pointers (hence, 1, 3, 5 in zero-based indexing).
CodePudding user response:
template <int N, typename Arg, typename... Args>
void helper(std::vector<std::pair<int, void*>>& v, Arg arg, Args... args) {
if constexpr(std::is_pointer_v<Arg>) {
v.emplace_back(N, (void*)arg);
}
if constexpr(sizeof...(args) > 0) {
helper<N 1, Args...>(v, args...);
}
}
template <typename... Args>
std::vector<std::pair<int, void*>> check(Args... args) {
std::vector<std::pair<int, void*>> ret;
helper<0>(ret, args...);
return ret;
}
Maybe a simpler version using fold expression
template <typename Arg>
void helper(std::vector<std::pair<int, void*>>& v, Arg arg, int idx) {
if constexpr(std::is_pointer_v<Arg>) {
v.emplace_back(idx, (void*)arg);
}
}
template <typename... Args>
std::vector<std::pair<int, void*>> check(Args... args) {
std::vector<std::pair<int, void*>> ret;
int n = 0;
(helper(ret, args, n ), ...);
return ret;
}
CodePudding user response:
There is no need to use recursion. In C 17, you can just combine fold-expression and immediately-invoked lambda to do this
template <typename... Args>
std::vector<std::pair<int, void*>> check(Args... args) {
std::vector<std::pair<int, void*>> ret;
int i = 0;
([&](auto arg) {
if constexpr (std::is_pointer_v<decltype(arg)>)
ret.emplace_back(i, arg);
i ;
}(args), ...);
return ret;
}