Stack Overflow Asked by blakcy88 on December 18, 2020
Trying to learn C++ coming from Python, and in python a set can have multiple types. How do I do this in C++? I’m specifically trying to have a set with both integers and strings. For example:
#include <set>
#include <string>
using namespace std;
int main() {
set<int, string> s;
s.insert(1);
s.insert("string");
}
Having multiple types of elements in a container is called a heterogenous container.
C++ supports this from C++17 using std::any which can hold any type, or as EOF said using std::variant when you want to define the set of possible types yourself.
Here is a demo of std::any
using std::any_cast:
#include <any>
#include <iostream>
#include <list>
#include <map>
#include <set>
int main()
{
std::list<std::any> any_list;
int myInt = 1;
std::string myString("I'm a string");
using MapType = std::map<std::list<int>, std::string>;
MapType myMap;
struct CustomType {
void* pointer;
};
any_list.emplace_back(std::any());
any_list.emplace_back(myInt);
any_list.emplace_back(myString);
any_list.emplace_back(myMap);
any_list.emplace_back(CustomType());
// To show the awesome power of std::any we add
// the list as an element of itself:
any_list.emplace_back(any_list);
for(auto& element: any_list) {
if(!element.has_value()) {
std::cout << "Element does not hold a value" << std::endl;
continue;
}
if (int* someInt = std::any_cast<int>(&element)) {
std::cout << "Element is int: " << *someInt << 'n';
} else if (std::string* s = std::any_cast<std::string>(&element)) {
std::cout << "Element is a std::string: " << *s << 'n';
} else if (std::any_cast<MapType>(&element)) {
std::cout << "Element is of type MapTypen";
} else if (std::any_cast<CustomType>(&element)) {
std::cout << "Element is of type CustomTypen";
} else {
std::cout << "Element is of unknown but very powerful typen";
}
}
}
This yields output:
Element does not hold a value
Element is int: 1
Element is a std::string: I'm a string
Element is of type MapType
Element is of type CustomType
Element is of unknown but very powerful type
The pre-C++17 method of doing this is obviously a struct
with manual type info and void*
.
Note that I used std::list
instead of std::set
because std::any
does not have operator<
defined by default. This could be solved by defining your own comparison predicate.
My personal opinion is that usually when you think you want to use a heterogenous container it's worth re-evaluating your design and stick to normal homogenous containers, but it's there if you need it :-)
Answered by VexingParse on December 18, 2020
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP