【问题标题】:How can I have a C++ set with more than 1 data type?我怎样才能拥有超过 1 种数据类型的 C++ 集?
【发布时间】:2020-10-17 22:03:53
【问题描述】:

尝试从 Python 中学习 C++,而在 Python 中,一个集合可以有多种类型。我如何在 C++ 中做到这一点?我特别想拥有一个包含整数和字符串的集合。例如:

#include <set>
#include <string>
using namespace std;

int main() {
    set<int, string> s;
    s.insert(1);
    s.insert("string");
    
}

【问题讨论】:

  • set&lt;variant&lt;int,string&gt;&gt;?
  • @πάνταῥεῖ 我也不确定,但老实说,我什至更不确定这什么时候有必要甚至什么时候有用。
  • 你不能有两个不同的集合吗?只需通过键的类型,您就知道它应该属于哪个集合。
  • @WhozCraig 由于 OP 只是在学习,我希望他们能够使用他们想要的任何闪亮的最新编译器。 :)

标签: c++ c++11 set


【解决方案1】:

在一个容器中拥有多种类型的元素称为异构容器

C++ 从 C++17 开始支持这一点,使用可以保存任何类型的 std::any,或者当你想自己定义一组可能的类型时,使用 std::variantas EOF said

这是std::any 使用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 MapType\n";
        } else if (std::any_cast<CustomType>(&element)) {
            std::cout << "Element is of type CustomType\n";
        } else {
            std::cout << "Element is of unknown but very powerful type\n";
        }
    }
}

这会产生输出:

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

C++17 之前的方法显然是带有手动类型信息的structvoid*

请注意,我使用了std::list 而不是std::set,因为std::any 默认没有定义operator&lt;。这可以通过定义自己的比较谓词来解决。

我个人的看法是,通常当你认为你想要使用异构容器时,值得重新评估你的设计并坚持使用普通的同质容器,但如果你需要它就在那里 :-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    相关资源
    最近更新 更多