【问题标题】:C++ Template Wildcard-like construct (or: How can I make Wildcards with a Template)C++ 模板通配符类构造(或:如何使用模板制作通配符)
【发布时间】:2021-02-04 14:05:05
【问题描述】:

所以,正如您可能已经想象的那样,我正在尝试在 C++ 中使用通配符。但首先,让我举一个例子来说明我的意思: 假设我们有一个 Human 类和一个 Pocket 类。 Pocket 类有一个任意的其他类作为类型参数。为了更好地可视化这一点,让我们编写一些代码(在 Java 中:)

人类.java:

package de.budschie.human_pocket_example;

import java.util.ArrayList;

public class Human 
{
    ArrayList<Pocket<?>> inventory = new ArrayList<>();
}



Pocket.java:

package de.budschie.human_pocket_example;

public class Pocket<E>
{
    E pocketElement;
    int amount;
    
    public Pocket(E pocketElement, int amount) 
    {
        this.pocketElement = pocketElement;
        this.amount = amount;
    }
    
    public E getPocketElement() 
    {
        return pocketElement;
    }
    
    public int getAmount() {
        return amount;
    }
}



如您所见,我可以存储口袋,而不管它们的类型参数如何。我可以创建一个包含一个包含整数的口袋和另一个包含浮点数的口袋,两者都可以放入库存中。所以,我的问题是:

我将如何在 C++ 中做到这一点?

我已经尝试使用问号,但这似乎不起作用。我不能只说,我想要一个 std::vector>。

我希望这不是 StackOverflow 的主题,如果是,请在cmets,我会尽快删除这个问题。

【问题讨论】:

  • 你能展示你的 c++ 代码吗?什么不适合你?你是如何尝试使用它的? template &lt;typename T&gt; void foo(std::vector&lt;Pocket&lt;T&gt;&gt; vec) {}可以支持任意Pocket&lt;T&gt;
  • 我建议选择a good C++ book。您想要做的将在那里解释为“模板”。

标签: c++ templates generics


【解决方案1】:

您需要处理 Java 和 C++ 之间的三个关键区别:类型系统不同,模板不是泛型,向量不是数组列表。

  1. 类型系统:

    在 Java 中,Pocket&lt;E&gt; 的每个实例化仍然派生自 Object,因此有一些通用的基类型来存储引用。

    在 C++ 中,Pocket&lt;E&gt; 的每个实例化都是不同的类型,并且不存在根类型的隐式继承。如果您希望每个 Pocket&lt;E&gt; 都派生自某个东西,则必须手动执行此操作。

  2. 又是类型系统:

    假设您为层次结构添加了一个根 PocketBase,每个 Pocket&lt;E&gt; 都从该根派生。 由于没有根类型,因此不同的E 类型也没有通用的基类,因此不同的Pocket&lt;E&gt;::getPocketElement() 也没有通用的返回类型。

    你可以让它返回std::any,我猜,如果这有意义的话。但是你可以直接在PocketBase 中使用std::any,因为Pocket&lt;T&gt; 并没有做更多的事情。

  3. std::vector 存储对象。如果你想要多态,你需要存储指针。同样,您需要明确地执行此操作:std::vector&lt;std::unique_ptr&lt;PocketBase&gt;&gt; 或其他任何内容。

基本的层次结构是这样的:

class PocketBase
{
protected:
  int amount_ = 0;

public:
  virtual ~PocketBase() = 0;

  int amount() const { return amount_; }
};

template <typename T>
class Pocket: public PocketBase
{
  T element_;
public:
  // etc. etc.
};

现在

std::vector<std::unique_ptr<PocketBase>>

可以存储(指向)Pocket&lt;T&gt; 类型的任何混合。

【讨论】:

    【解决方案2】:

    我建议将Pocket 设为非模板类​​,并在其中保留一个std::any 属性以存储任何类型的值。

        struct Human {
            struct Pocket {
                std::any thing; 
                std::size_t quantity;
            };
            std::vector<Pocket> pockets;
        };
    

    【讨论】:

      猜你喜欢
      • 2012-11-21
      • 1970-01-01
      • 1970-01-01
      • 2013-11-21
      • 1970-01-01
      • 2015-12-08
      • 2022-08-16
      • 1970-01-01
      相关资源
      最近更新 更多