Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass a single parameter to a function that expects an iterator range

Tags:

Consider a function that accepts one or more parameters (e.g. file names). In order to make it versatile, it is advantageous to write it for a general iterator range:

template<class Iter> void function(Iter first, Iter last) {   // do something } 

Now we can invoke it in the following way, independently of how we store the arguments:

WhateverContainer container; function(std::begin(container), std::end(container)); 

For example, the STL relies heavily on this paradigm.

Now, imagine we want to invoke the function with a single argument that is not stored in a container. Of course we can write:

const int value = 5; std::vector<int> vec(1, value); function(std::begin(vec), std::end(vec)); 

But this solution seems clumsy and wasteful to me.

Question: Is there a better low-overhead way of creating an iterator-range-compatible representation of a single variable?

like image 844
piripiri Avatar asked May 04 '18 11:05

piripiri


2 Answers

You can use pointers, for once:

function(&value, &value + 1); 

In generic code, std::addressof instead of the unary operator & is somewhat safer, depending on your level of paranoia.

You can of course wrap this in an overload for easier use:

template <class T> decltype(auto) function (T &&e) {     auto p = std::addressof(e);     return function(p, p + 1); } 
like image 69
Baum mit Augen Avatar answered Sep 20 '22 17:09

Baum mit Augen


You can treat it like an array of one element per [expr.unary.op]/3:

function(&value, &value + 1); 

For purposes of pointer arithmetic ([expr.add]) and comparison ([expr.rel], [expr.eq]), an object that is not an array element whose address is taken in this way is considered to belong to an array with one element of type T.

like image 39
chris Avatar answered Sep 17 '22 17:09

chris