【问题标题】:Use of incomplete types with std::variant在 std::variant 中使用不完整类型
【发布时间】:2021-12-28 20:32:17
【问题描述】:

假设我有下一个代码,用于简单地存储类型为ABC 的对象的引用/指针。我实际上不需要完整的类型。

现在我有以下解决方案,我需要很多 #include 膨胀。

标题:

using MyVariant = std::variant<class A, class B, class C, ...>;

class Holder {
public:
  Holder(MyVariant &&TheValue);

  const MyVariant &GetValue();
  
private:
  std::unique_ptr<MyVariant> Value;
};

源文件:

#include "A.hpp"
#include "B.hpp"
#include "C.hpp"

Holder::Holder(MyVariant &&TheValue)
  : Value(std::make_unique<MyVariant>(std::move(TheValue)) {}

const MyVariant &Holder::GetValue { return Value; }

如何在没有所有实例化类型的情况下实现与 std::variant 模板参数/动态内存分配/动态多态性相同的语义?

【问题讨论】:

  • 如果你只是想持有指针,那为什么不std::variant&lt;A*, B*, C*&gt;呢? (或std::unique_ptr 等效项)。
  • 我想避免很多new 调用,所以我不能在堆栈上分配对象并将指针传递给它。而不是这个,我通常希望自己持有一个值。
  • 在您当前的解决方案中,为什么使用std::unique_ptr&lt;MyVariant&gt; Value; 而不是MyVariant Value;?即使对于自动 Holder 实例,这也会将变体放入堆栈中。
  • @385i 如果您希望std::variant 实际保存没有间接的类型,那么它们在逻辑上必须是完整的,因为std::variant 需要知道为它们保留多少内存。
  • @385i variant 不能用于不完整的类型,原因相同,没有任何解决方法可以满足您的所有要求。您希望对象就地存储值(没有外部存储器)。为此,对象必须至少与它可以容纳的最大类型一样大。为此,它必须知道它可以容纳的每种类型的大小。为此,每种类型都必须是完整的(您无法获得不完整类型的大小),这与您对类型不完整的要求相矛盾。

标签: c++ polymorphism variant


【解决方案1】:

正如其他人指出的那样,规格似乎有点矛盾。 我只能想到可变模板参数,以实现不必为Holder 类指定所有可能的类。

Example

#include <iostream>
#include <memory>
#include <variant>

// h

template<typename ...T>
class Holder {
  using variant = std::variant<T...>;
public:
  Holder(variant &&TheValue) 
  :Value(std::make_unique<variant>(std::move(TheValue)))
  {
  };
  
  template<typename TARGET>
  const TARGET &GetValue() const {
    return std::get<TARGET>(*Value);
  };
  
private:
  std::unique_ptr<variant> Value;
};

// main.cpp testing
int main() {
  auto a = Holder<int, float>(5);
  const auto v = a.GetValue<int>();
  std::cout << "holding int: " << v << std::endl;

  a = Holder<int, float>(5.5f);
  const auto v2 = a.GetValue<float>();
  std::cout << "holding float: " << v2 << std::endl;
} 

我认为在这一点上它看起来像是一个相当多余的类。

【讨论】:

    猜你喜欢
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 2019-05-13
    • 2017-02-22
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多