HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppModerate

Variadic templated method to extract values from a table

Submitted by: @import:stackexchange-codereview··
0
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 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

/* 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.