C++ The Any Type
A std::any holds one value, and that value can be of any type. The type is not fixed in advance, so each read names the expected type.
Holding an int
The any starts with the int 7. std::any_cast<int> reads it back, and has_value confirms a value is held.
#include <any>
#include <iostream>
int main() {
std::any box = 7;
std::cout << std::boolalpha;
std::cout << std::any_cast<int>(box) << "\n";
std::cout << box.has_value() << "\n";
return 0;
}The type follows the value
The same any holds an int, then a string, then a double. Each read names the type that was stored last.
#include <any>
#include <iostream>
#include <string>
int main() {
std::any box = 7;
std::cout << std::any_cast<int>(box) << "\n";
box = std::string("hello");
std::cout << std::any_cast<std::string>(box) << "\n";
box = 2.5;
std::cout << std::any_cast<double>(box) << "\n";
return 0;
}A wrong cast is caught
The any holds a string, so a cast to int fails. The catch block prints the message that what() gives for the error.
#include <any>
#include <iostream>
#include <string>
int main() {
std::any box = std::string("hello");
try {
int number = std::any_cast<int>(box);
std::cout << number << "\n";
} catch (const std::bad_any_cast& error) {
std::cout << error.what() << "\n";
}
std::cout << "Program continues" << "\n";
return 0;
}An empty box
A fresh any holds nothing, so has_value gives false. A value is stored, reset runs, and the box is empty again.
#include <any>
#include <iostream>
int main() {
std::any box;
std::cout << std::boolalpha;
std::cout << box.has_value() << "\n";
box = 42;
std::cout << box.has_value() << "\n";
box.reset();
std::cout << box.has_value() << "\n";
return 0;
}Example
#include <any>
#include <iostream>
#include <string>
#include <typeinfo>
#include <vector>
int main() {
std::vector<std::any> bag;
bag.push_back(10);
bag.push_back(std::string("pen"));
bag.push_back(5);
bag.push_back(2.5);
int total = 0;
int counted = 0;
for (const std::any& item : bag) {
bool isInt = item.type() == typeid(int);
if (isInt) {
total += std::any_cast<int>(item);
counted += 1;
}
}
std::cout << "Int total: " << total << "\n";
std::cout << "Ints counted: " << counted << "\n";
std::cout << "Items: " << bag.size() << "\n";
return 0;
}Key points
- The <any> header gives a program the std::any type.
- has_value() tells whether an any currently holds a value.
- std::any_cast<T> reads the held value when the stored type matches T.
- A cast with the wrong type throws std::bad_any_cast.
- reset() empties an any, and has_value() then gives false.
- type() identifies the stored type, and a comparison against typeid gives a plain true or false answer.
In this example, a vector holds four values of different types, each inside an any. Each item is compared against typeid(int), and that comparison gives a plain true or false answer. Only the two ints are cast and added, so the total is 15 out of four items.
Note
A variant lists its possible types in advance, while an any leaves the type open.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
An any holds a string. What happens when std::any_cast<int> runs on it inside a try block?