An object or function reference of type T can be encapsulated within a copy constructible by employing the std::referencewrapper class template. Instances of std::referencewrapper can be duplicated or held in containers, and they are automatically transformable to "T&" for seamless utilization as reference arguments in functions that require the base type by reference.
When direct usage of raw references is not possible, the std::reference_wrapper function can be employed to store references in containers or transfer them as function parameters.
The std::reference_wrapper is commonly employed in algorithms that deal with references in a polymorphic manner. It is utilized for passing references to functions that require arguments by value and for storing references in containers.
Syntax:
It has the following syntax:
template <class T> class reference_wrapper;
template parameter(T): type of the referred element and this can be either function or object.
Example 1:
Let's consider a scenario to demonstrate the std::reference_wrapper in the C++ programming language.
#include <iostream>
#include <functional>
#include <vector>
void modify(int& x) {
x *= 2;
}
int main() {
int value = 10;
std::vector<std::reference_wrapper<int>> vec;
// Store references in the vector using std::reference_wrapper
vec.push_back(std::ref(value));
vec.push_back(value); // Alternatively, you can use std::ref() directly
// Modify the original value through the reference wrappers
for(auto& ref : vec) {
modify(ref);
}
// Original value has been modified
std::cout << "Modified value: " << value << std::endl;
return 0;
}
Output:
Modified value: 40
Explanation:
In this instance, a function called alter accepts references that are handed over to it for alteration through std::referencewrapper, allowing references to be stored in a std::vector. In general, the std::referencewrapper provides a flexible and safe approach to handling references in scenarios where using references directly is neither ideal nor feasible.
Example 2:
Let's consider another scenario to demonstrate the application of std::reference_wrapper in the C++ programming language.
#include <iostream>
#include <functional>
#include <vector>
// Function to double the value of the referenced integer
void doubleValue(int& x) {
x *= 2;
}
int main() {
// Create a vector to store references to integers
std::vector<std::reference_wrapper<int>> intRefs;
// Some integer values
int a = 5;
int b = 10;
int c = 15;
// Store references to these integers in the vector
intRefs.push_back(std::ref(a));
intRefs.push_back(std::ref(b));
intRefs.push_back(std::ref(c));
// Double the values of all integers using std::reference_wrapper
for (int& ref : intRefs) {
doubleValue(ref);
}
// Print the modified values
std::cout << "Modified values:" << std::endl;
std::cout << "a: " << a << std::endl;
std::cout << "b: " << b << std::endl;
std::cout << "c: " << c << std::endl;
return 0;
}
Output:
Modified values:
a: 10
b: 20
c: 30
Explanation:
- In this example, the references to integers are kept in a vector called intRefs .
- We define a, b, and c, three integer variables.
- Using the std::ref function, references to these integers are kept in the vector.
- After that, we define a function called doubleValue to double the value of the referenced integer.
- By iterating through the reference vector and passing each reference to doubleValue, we are able to double the value of each integer that is referenced.
- Ultimately, we output the updated integer values.
Example 3:
Let's consider another instance to demonstrate the std::reference_wrapper in the C++ programming language.
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
// Function to print the value of the referenced integer
void printValue(int& x) {
std::cout << x << " ";
}
int main() {
// Create a vector of integers
std::vector<int> numbers = {4, 7, 2, 9, 5};
// Create a vector to store references to integers
std::vector<std::reference_wrapper<int>> numberRefs;
// Populate the vector of references
for (int& num : numbers) {
numberRefs.push_back(std::ref(num));
}
// Print original values
std::cout << "Original values: ";
std::for_each(numbers.begin(), numbers.end(), printValue);
std::cout << std::endl;
// Increment each value using std::reference_wrapper and std::for_each algorithm
std::for_each(numberRefs.begin(), numberRefs.end(), [](int& x) { x++; });
// Print modified values
std::cout << "Modified values: ";
std::for_each(numbers.begin(), numbers.end(), printValue);
std::cout << std::endl;
return 0;
}
Output:
Original values: 4 7 2 9 5
Modified values: 5 8 3 10 6
Conclusion:
In summary, in cases where direct utilization of references is not feasible or preferred, such as when managing references in containers or supplying them to algorithms requiring copyable elements, the std::referencewrapper in C++ presents a valuable and reliable solution for handling references. Functioning as a wrapper, std::referencewrapper encapsulates references within an object-like form, enabling the use of references in a polymorphic manner and scenarios where utilizing raw references would not be suitable, such as within standard containers like vectors or maps. Moreover, std::referencewrapper maintains reference semantics, ensuring that actions performed on the wrapper directly affect the original referenced object. Given its versatility and security features, std::referencewrapper serves as a valuable resource for developers looking to leverage references across various programming contexts while adhering to the constraints dictated by specific language constructs or library interfaces.