【问题标题】:Store the template that the class was initialized with存储类初始化的模板
【发布时间】:2015-04-16 10:42:57
【问题描述】:

我想弄清楚如何存储我的模板,我写一个例子:

class cDebugInfo
{
private:
    DWORD * address;
    string name;
    template Type;

public:
    Type GetFormattedValue()
    {
        return *(Type*)address;
    }
    cDebugInfo(){}
    template <class T>
    cDebugInfo(DWORD Address, string Name){
        address = Address;
        name = Name;
        Type = T;
    }
};

我的目标是能够将一个项目添加到我的数组中:

std::vector<cDebugInfo>DebugItems;

template <class T>
void AddItem(std::string name, DWORD Address)
{
    DebugItems.push_back(cDebugInfo(Address, name));
}
cDebugInfo* GetItemByNameP(std::string name)
{
    for (int i = 0; i < DebugItems.size(); i++)
    {
        if (DebugItems[i].name == name)
        {
            return &DebugItems[i];
        }
    }
}

所以我像这样将项目添加到我的数组中:

AddItem<int>(0x1337, "Test");
AddItem<string>(0x1337, "Test2");

因此能够调用:

GetItemByName("Test")->GetFormattedValue();

这应该返回从给定地址读取的 INT 值,因为当我添加项目时传递的模板是一个 int。当然,以下应该将存储在我的指针指向的地址中的值作为字符串返回:

GetItemByName("Test2")->GetFormattedValue();

我需要它来“记住”传递给班级的模板。 注意:当我将 GetItemByName 与模板一起使用时,其他一切都可以正常工作,但问题是当我得到它们时我不知道它是什么模板,只有当我添加它们时。 谢谢。

【问题讨论】:

  • GetItemByName("Test")-&gt;GetFormattedValue&lt;int&gt;(); 怎么样?
  • 有几种方法可以存储类型信息;困难的部分是如何提取它。在GetFormattedValue 的调用站点上,您需要静态地知道返回类型是什么(除非您想返回像 Boost.any 这样的有区别的联合)。奇怪的是,一个 formatted 值通常意味着一个字符串 - 你确定你不只是想控制格式并取回一个字符串吗?
  • @ixSci 是的,如果我也使用模板,如上所述,它可以工作。但我需要在不知道它是 int、bool 还是其他什么的情况下检索该值。
  • 你可以搜索 C++ 中的“类型擦除”,看看boost.any
  • 100% 动态在 C++ 中是不可能的。你想要的在 C++ 中是无法实现的。你最好的选择是 boost.any, boost.typeerasure 就像已经说过的那样。没有比这更好的了,因为 C++ 不支持这种程度的活力。

标签: c++ templates


【解决方案1】:

您要求的内容是不可能的,因为 C++ 中的每个表达式在编译时都必须具有已知类型。考虑一下:

auto value = GetItemByName("BestItem")->GetFormattedValue();

GetItemByName(...) 给了我一个cDebugInfo*,但是GetFormattedValue() 给了我什么?这对于每个cDebugInfo* 都必须是相同的类型,这样上述表达式才能有效,因此该类型直到运行时才能保留。所以一般的解决方案是不可能的。

但是,您可以根据自己的需要添加特定的解决方案。假设我们只想能够打印格式化的值。我们可以这样做:

class cDebugInfo {
    std::function<void()> printer; // type-erased functor
    ...
public:
    template <class T>
    cDebugInfo(DWORD Address, string Name){
        address = Address;
        name = Name;
        printer = [this]{
            std::cout << "Value as " << typeid(T).name() << ": "
                      << *reinterpret_cast<T*>(address) << '\n';
        };
    }
};

这种方法称为“类型擦除”。在这种情况下,lambda“存储”了 T 类型,但类本身只需要知道它是一个返回 void 的空函数。我们可以通过以下方式公开它:

void printValue() { printer(); }

这样:

GetItemByValue("BestItem")->printValue();

将根据构造它的类型正确打印值。

【讨论】:

  • 哇,谢谢,我的目标是将它存储在一个字符串中并打印在我的日志中,这正是我想要的:D
  • 您可以更轻松地存储文本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-08
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
相关资源
最近更新 更多