Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic for loop for elementary and complex type

Suppose I have those two std::vector:

std::vector<int> v_int(1000);
std::vector<T> v_T(1000); // Where T is copy-costy type

if I need to loop through them (sepereatly) without the need for editing the items I may use:

for(const auto item:v_int){
    //...
}

for(const auto& item:v_T){ //Note &
    //...
}

Iterating using const auto item:v_T is too bad since a copy will be performed in each iteration. However, using const auto& item:v_int is not optimal but not that bad. So if I need a code that deal with both them I used to use const auto& item:v.

Question: Is there a generic way to write the for loop that will use the best declaration for both of them? Something like:

template <typename T>
void iterate(const std::vector<T> v){
    for(const auto/*&*/ item:v){ // activate & if T is not elementary type
         //...
    }
}
like image 587
Humam Helfawi Avatar asked May 17 '16 09:05

Humam Helfawi


People also ask

What is Generic loop?

Java's Generic has a new loop called for-each loop. It is also called enhanced for loop. This for-each loop makes it easier to iterate over array or generic Collection classes.

What is a generic class in C++?

Generics in C++ Generics is the idea to allow type (Integer, String, … etc and user-defined types) to be a parameter to methods, classes and interfaces. For example, classes like an array, map, etc, which can be used using generics very efficiently. We can use them for any type.

What does for do in Java?

Loops in Java come into use when we need to repeatedly execute a block of statements. Java for loop provides a concise way of writing the loop structure. The for statement consumes the initialization, condition and increment/decrement in one line thereby providing a shorter, easy to debug structure of looping.


2 Answers

You can do this using the standard type traits:

template <typename T>
using select_type = std::conditional_t<std::is_fundamental<T>::value,
                                      const T, const T&>;

template <typename T>
void iterate(const std::vector<T> v){
    for(select_type<T> item:v){ // activate & if T is not elementary type
         //...
    }
}

However, I question the wisdom of doing this. It just clutters the code for something which is unlikely to make any difference.

like image 120
TartanLlama Avatar answered Oct 03 '22 10:10

TartanLlama


Use auto&& when you just don't care. Use auto const& when you must guarantee it is not edited.

References are aliases, and in an immediate context like a loop are trivial to optimize out of existence, especially if the value is never modified.

There are some difficulties when a reference is passed over a compilation unit boundary to a function, which is why passing int by value instead of const& is advised sometimes, but that does not apply here.

like image 32
Yakk - Adam Nevraumont Avatar answered Oct 03 '22 10:10

Yakk - Adam Nevraumont