【问题标题】:C++ Heterogeneous listC++ 异构列表
【发布时间】:2017-12-23 21:11:27
【问题描述】:

几周以来,我一直在互联网上搜索有关 c++ 中的异构列表(vectorarraylist),但是,在所有站点和论坛中,答案都是相同的:boost::any,但是我想要一种在纯 C++ 中做到这一点的方法。我开发了这个:

#include <iostream>
#include <typeinfo>
#include <vector>

using namespace std; 
 //Compiler version g++ 6.3.0

 class any
 {
 public:
    auto get() {}
 };

 template<typename T>
 class anyTyped : public any
 {
 public:
    T val;

    anyTyped(T x)
    {
        val = x;
    }
    T get()
    {
        return val;
    }
 };

 class queue
 {
    vector<any*> x;
    int len = 0;

 public:
    queue()
    {
        x.resize(0);
    }

    template<typename T>
    void insert(T val)
    {
        any* ins = new anyTyped<T>(val);
        x.push_back(ins);
        len++;
    }
    int size()
    {
        return len;
    }

    auto& at(int idx)
    {
        return x[idx]->get();
    }
 };

 int main()
 {

    queue vec;

    vec.insert(5);     //int
    vec.insert(4.3);   //float
    vec.insert("txt"); //string

    for (int i = 0; i < vec.size(); i++)
    {
        cout << vec.at(i);
    }

    return 0;
 }

但我得到这个错误:

source_file.cpp: In member function 'auto& queue::at(int)':
source_file.cpp:55:23: error: forming reference to void
    return x[idx]->get();
                       ^
source_file.cpp: In function 'int main()':
source_file.cpp:70:9: error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'void')
    cout << vec.at(i);
    ~~~~~^~~~~~~~~~~~

我知道问题在于使用 auto 作为返回类型,在 any 类中的 auto get()queue 类中的 auto&amp; at(int idx) 中,但我不知道如何修复。

【问题讨论】:

  • 在 C++ 17 中,添加了 std::any。
  • 根据我的经验,创建自己的“任何”类非常困难且不直观,因此历史上唯一流行的实现是 Boost 和最近的 C++17。我建议你尽量不要重新发明轮子,除非你有特定的理由。我还建议您尝试使用 std::variant 之类的东西,而不是 any,因为您对类型的了解越多越好。
  • boost::any 纯 C++。另外,您希望auto get() {} 做什么?它无法推断出auto 的类型,也不会返回任何内容。
  • @nwp 我假设他的意思是没有导入像 Boost 这样大的库。
  • @nwp, auto get() {} 只是为了实现T get() 之后。

标签: c++ heterogeneous-array


【解决方案1】:

为了存储,所有异构数据都必须在 C++ 中归结为同质数据。 std::any 也不例外。为了使事物同质化,最重要的是继承和类型擦除(any 是后者的一个实例)。

应用于您的示例,这可能意味着,例如,您必须将 get 的返回类型指定为固定类型。在最好的情况下,这将是您使用的所有类型T 中的std::common_type

得到这个想法:

anyTyped<double> anyDouble{1.0};
anyTyped<int> anyInt{2};

std::vector<std::function<double()> > anyStore;  //the chosen homogenous type is 'double'

//get() should be const, otherwise add a 'mutable'
anyStore.push_back([anyDouble]() { return anyDouble.get(); });
anyStore.push_back([anyInt]() { return anyInt.get(); });

你现在可以打电话了

auto x = anyStore[0]();   //x is a double
x = anyStore[1]();

在这两种情况下你都会得到一个double,但你不会取回你的int

所有处理异构构建的运行时都基于类似的原则,但可能更复杂——这基本上意味着涉及更多层,直到链以同构类型结束。

【讨论】:

    【解决方案2】:

    您的any 课程存在固有缺陷,我建议您在将其添加到队列之前解决这些问题。

    主要问题是 C++ 是一种静态类型语言,从 vec.at(i) 中提取值很可能需要某种类型的类型信息:vec.at&lt;int&gt;(i)

    您的any 实现将更加健壮、更加智能地按照您的预期工作。使用boost/any.hppstd::any。如果您不想包含整个 boost,请尝试仅包含 any 标头或查找 any 库的单个标头实现。

    在您的情况下,您的队列实现并没有什么特别之处,因为异质性将包含在 any 类型中。

    如果您真的想实现自己的,请查看 boost 的实现,看看您是否可以从中派生。它不会像您对动态类型语言所期望的那样简单。

    http://www.boost.org/doc/libs/1_55_0/boost/any.hpp

    最后,您需要指定要从any 类中提取的数据类型。

    【讨论】:

      猜你喜欢
      • 2015-02-24
      • 2014-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-13
      • 1970-01-01
      相关资源
      最近更新 更多