patterncppModerate
Variadic templated method to extract values from a table
Viewed 0 times
templatedmethodvariadicextractvaluesfromtable
Problem
Is this the correct, most sane way to do variadic templates in C++?
All that this function does is to see if gate has a key, if it has, it adds it to a vector of values, if not, it default constructs an object in place.
This function belongs to a templated class called
I'm asking it because all the examples of variadic templates that I saw until now made use of recursion. I'm still in a state of desbelief that I can just write
So, is this a good example? How can I make it better, more optimized?
Working Example
```
#include
#include
#include
#include
#include
using std::cout;
using std::endl;
template
class core_table {
using value = std::pair;
using chain = std::list;
using iterator = typename chain::iterator;
using const_iterator = typename chain::const_iterator;
struct compare {
using is_transparent = void;
bool operator ()(const_iterator x, const_iterator y) const {
return x->first first;
}
bool operator ()(const_iterator x, K const & k) const {
return x->first first;
}
};
chain data;
std::set gate;
public:
core_table() = default;
core_table(core_table && ct) = default;
core_table(core_table const & ct) {
for (auto const & e : ct) {
push(e.firs
All that this function does is to see if gate has a key, if it has, it adds it to a vector of values, if not, it default constructs an object in place.
This function belongs to a templated class called
core_table where K is the key type and V the value type.template
std::vector values_at(Args const & ...args) const {
std::initializer_list input {args...};
std::vector output;
output.reserve(input.size());
for (auto const & e : input) {
auto const it = gate.find(e);
if (it != gate.end()) {
output.emplace_back((*it)->second);
continue;
}
output.emplace_back();
}
return output;
}I'm asking it because all the examples of variadic templates that I saw until now made use of recursion. I'm still in a state of desbelief that I can just write
std::initializer_list input {k, args...}; and iterate over it, I literally didn't knew until now that this was possible - this does make variadic templates much more approachable in C++, at least for me.So, is this a good example? How can I make it better, more optimized?
Working Example
```
#include
#include
#include
#include
#include
using std::cout;
using std::endl;
template
class core_table {
using value = std::pair;
using chain = std::list;
using iterator = typename chain::iterator;
using const_iterator = typename chain::const_iterator;
struct compare {
using is_transparent = void;
bool operator ()(const_iterator x, const_iterator y) const {
return x->first first;
}
bool operator ()(const_iterator x, K const & k) const {
return x->first first;
}
};
chain data;
std::set gate;
public:
core_table() = default;
core_table(core_table && ct) = default;
core_table(core_table const & ct) {
for (auto const & e : ct) {
push(e.firs
Solution
Yes, it is a good example
Variadic templates are associated with recursion by similarity to functional programming, where an recursion is a simple method of operating on sequences. Direct expansion is akin to a map or fold, or some other higher-order function.
It can be simplified even more
If you have a similar function
Then you can condense this down into a single expression
as that expands the parameter pack into multiple calls to
Variadic templates are associated with recursion by similarity to functional programming, where an recursion is a simple method of operating on sequences. Direct expansion is akin to a map or fold, or some other higher-order function.
It can be simplified even more
If you have a similar function
/* find value or return default */
template
V value_at(Arg const & key) const
{
auto const it = gate.find(key);
if (it != gate.end()) {
return it->second;
}
return {};
}Then you can condense this down into a single expression
return vector({value_at(args)...});as that expands the parameter pack into multiple calls to
value_at, which goes into vector's std::initializer_list constructor.Code Snippets
/* find value or return default */
template <typename Arg>
V value_at(Arg const & key) const
{
auto const it = gate.find(key);
if (it != gate.end()) {
return it->second;
}
return {};
}return vector<V>({value_at(args)...});Context
StackExchange Code Review Q#154586, answer score: 10
Revisions (0)
No revisions yet.