patterncppMinor
Selecting variable amount of vector elements in C++
Viewed 0 times
elementsamountselectingvariablevector
Problem
Suppose we are given a C++ vector. We want to specify a variable amount of indices and select elements from a vector being indexed. I have two implementation: (A) one relies on C++11 initializer lists, and the second one (B) on
So my main question is: which one should an adult C++ programmer use, if any?
coderodde.h:
The test driver main.cpp:
va_list and macro mess. Arrangement B is however funkier to type because it requires no typing the braces comprising the initializer list. So my main question is: which one should an adult C++ programmer use, if any?
coderodde.h:
#ifndef CODERODDE_H
#define CODERODDE_H
#include
#include
#include
#define NUM_ARGS(...) (sizeof((size_t[]){__VA_ARGS__}) / sizeof(size_t))
namespace coderodde {
template
std::vector select(const std::vector& vec,
const std::vector& indices)
{
std::vector ret;
for (auto index : indices) {
ret.push_back(vec.at(index));
}
return ret;
}
template
std::vector select(const std::vector& vec, const size_t len, ...)
{
std::va_list ap;
std::vector ret;
va_start(ap, len);
for (size_t i = 0; i < len; ++i)
{
ret.push_back(vec.at(va_arg(ap, size_t)));
}
va_end(ap);
return ret;
}
}
#define SELECT(vec, ...) (select(vec, NUM_ARGS(__VA_ARGS__), __VA_ARGS__))
#endif // CODERODDE_HThe test driver main.cpp:
#include
#include
#include
#include "coderodde.h"
using std::cout;
using std::endl;
using std::string;
using std::vector;
using coderodde::select;
void test_smart(const vector& input)
{
const size_t N = input.size();
for (size_t ca = 0; ca & input)
{
const size_t N = input.size();
for (size_t ca = 0; ca string_vec {"A", "B", "C", "D"};
cout << "Smart:" << endl;
test_smart(string_vec);
cout << "Stupid:" << endl;
test_stupid(string_vec);
return 0;
}Solution
You can avoid problems related to variadic macros and problems related to C-style variadic functions altogether by creating a function that takes an
Moreover, it is the easiest to read of the three implementations.
std::initializer_list directly:template
std::vector select(const std::vector& vec, std::initializer_list indices)
{
std::vector ret;
for (std::size_t ind: indices)
{
ret.push_back(vec.at(ind));
}
return ret;
}Moreover, it is the easiest to read of the three implementations.
Code Snippets
template<class T>
std::vector<T> select(const std::vector<T>& vec, std::initializer_list<std::size_t> indices)
{
std::vector<T> ret;
for (std::size_t ind: indices)
{
ret.push_back(vec.at(ind));
}
return ret;
}Context
StackExchange Code Review Q#83115, answer score: 5
Revisions (0)
No revisions yet.