当前位置: 首页 > 知识库问答 >
问题:

仅从一个模板参数中查找特定模板。有可能吗?

萧元徽
2023-03-14

假设我有这样的东西:

template <typename T, typename ...args>
static std::map<T, std::tuple<args...>> MyMaps;

每种类型在编译时都是已知的。因此,对于添加到映射中的每个类型配置,都会创建一个新的映射。

是否有一种方法可以在所有匹配T参数的映射实例中仅搜索关键字(和关键字类型)?

编辑:对不起,我的问题太简单了。我害怕把它做得太大,最后它错过了我的意图。但我想,正如@Quimby所解释的那样,我试图实现的目标是不可能实现的。

我真正想做的是一个debug助手(实际上是虚幻的),来跟踪对象值,比如一个可包含的. h(Debbughelper. h):

#include <tuple>
#include <vector>
#include <type_traits>

#define WATCHMYOBJECT(object, ...) //TO DO
#define RESCANMYOBJECT(object) //TO DO

template <typename ...T>
void Expand(T...args)
{
    return;
}

template <typename T, typename ...args>
class MyWatcherClass
{
public:
    static void WatchMyObject(T &object, args& ...b);
    static void RescanMyObject(T& MyObject);
    static std::vector<MyWatcherClass*> Instaces;

private:
    std::tuple<args...> MyTuple = std::tuple<args...>();
    std::vector<void*> VoidPointerStorage;
    T* MyObjectPointer;

private:
    MyWatcherClass();
    ~MyWatcherClass();
};

template <typename T, typename ...args>
void MyWatcherClass<T, args...>::WatchMyObject(T &MyObject, args& ...b)
{
    MyWatcherClass<T, args...>* MyClassPointer = new MyWatcherClass;
    InstacedObjects.push_back(MyClassPointer);
    MyObjectPointer = &MyObject;
    int helpint = 0;
    MyClassPointer->MyTuple = std::make_tuple(b...);
    Expand((MyClassPointer->PointerStorage.push_back((void*)&b),1)...);
}

template <typename T, typename ...args>
void MyWatcherClass<T, args...>::RescanMyObject(T &MyObject)
{
    // I have yet to implement, but impossible to call this
    // Compare Instaces[i].MyObjectPointer with &MyObject to find the matching one
    // cast all the void pointers in std::vector<void*> VoidPointerStorage back to typed pointers using the tuple types
    // Get the values derefing the pointers and update on the screen, log, etc
}

然后,在一些宏观魔法的帮助下,有人可以做到:

// #include <"debbughelper.h">
class MyNormalClass
{
public:
    MyNormalClass(int _MyInt, float _MyFloat, std::string _MyString);
    int MyInt;
    float MyFloat;
    std::string MyString;
};

MyNormalClass::MyNormalClass(int _MyInt, float _MyFloat, std::string _MyString) : MyInt(_MyInt), MyFloat(_MyFloat), MyString(_MyString)
{
}

int main()
{
   MyNormalClass MyObject = MyNormalClass(1, 5.2f, std::string("hello"));
   WATCHMYOBJECT(MyObject, MyObject.MyInt, MyObject.MyFloat, MyObject.MyString);

// do other stuff

   RESCANMYOBJECT(MyObject); //easy, without the need to retype all the members
}

但如果没有成员的类型,就无法调用RescanMyObject。

共有2个答案

王豪
2023-03-14

取决于您所说的搜索是什么意思。您可以将它们收集到容器中,然后执行您喜欢的任何类型的处理:

#include <any>
#include <iostream>
#include <map>
#include <typeindex>
#include <vector>

std::map<std::type_index,       // key type
         std::vector<std::any>  // pointers to the maps with this key type
         >
    key_to_map;

template <typename T, typename... args>
auto& MyMap() {
  static std::map<T, std::tuple<args...>> map = [] {
    key_to_map[std::type_index(typeid(T))].push_back(&map);
    return decltype(map){};
  }();

  return map;
}

int main() {
  MyMap<int, char, double>();
  MyMap<char, int, double>();
  MyMap<int, short, long>();

  std::cout << "Number of maps with `int` as the key is "
            << key_to_map[std::type_index(typeid(int))].size() << '\n';
}
沈龙光
2023-03-14

不。

要解决的根本问题是确定模板变量是否已实例化。否则,在无数可能的实例中寻找乐趣。

C 语言没有提供回答此类问题的工具,因为实现几乎是不可能的。主要是由于分离的编译和链接过程。博士;将是翻译单元 (TU) 尚未包含足够的信息,并且链接器为时已晚,因为代码已经生成。

每个翻译单元都单独编译到一个对象文件中。每个 TU 都看到了(希望是相同的)模板定义,从中实例化了此 TU 中使用的所有变量。但它不知道也不能知道其他 TU 中的任何实例化变量。

链接器的工作是收集所有这些目标文件,解析导出的和缺失的符号,包括< code >内联定义的重复数据删除,并最终创建可执行文件/库。

只有在最后一步之前,这个问题才能得到回答。但此时,代码已经生成,无法更改。即使编译器可能再次创建新代码,如果新代码生成更多的实例化,链接器是否应该再次尝试?这接近于运行时反射。

 类似资料:
  • 我有以下问题:一个类模板a,有几个模板参数,我想构建一个类B,它以a为模板参数,并提取a的第一个模板参数,以便在某种方法中使用它(想想从std::vector 中提取int并返回默认的int{})。 我知道这种天真的方法不会编译,但我不知道如何实现这样的东西。感谢任何提示。

  • 在C++11之前,类模板和函数模板只能含有固定数量的模板参数。C++11增强了模板功能,允许模板定义中包含0到任意个模板参数,这就是可变参数模板。可变参数模板的加入使得C++11的功能变得更加强大,而由此也带来了许多神奇的用法。 可变参数模板 可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面带上省略号...: template<ty

  • 我试图在类型s. t上专门化一个类。它忽略了给定类型的恒定性。在这种情况下,该类型是一个模板模板参数: 上面的代码在GCC 4.8.4和clang 5.0(with-std=c 11)中都抱怨bar在与匹配FOFType模板参数化的类一起使用时未定义。即使我删除了sfinae参数,仍然无法找到特化。 这个问题的一个例子可以在这里找到:https://godbolt.org/g/Cjci9C.在上面

  • 我有一个函数,它使用Boost进行base64编码。它有两个模板参数:一个用于输入的容器类型,另一个用于输出的容器类型。这允许您使用提供二进制数据,但可以返回。 这是代码: 用法示例: 这里有活样品 请注意,在上面的示例中,我仍然必须为输出容器提供模板参数,即使它与输入容器的类型相同。在这些场景中,我希望模板参数是可选的,而是使用由推导的类型。我不确定我可以执行什么变通或调整来获得这种界面,但很高

  • (...)“m”不约束类型(...)

  • 以下程序在C 20中编译良好: 但在C 17中,它会产生一个错误: 你能告诉我C20有什么变化让它工作吗?