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

Finding a specific template from just one template parameter. Is it possible?

假设我有这样的东西:

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

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

有没有一种方法可以在所有与 T 参数匹配的映射实例中仅使用键(和键类型)进行搜索?

编辑:很抱歉超级简化了我的问题。我害怕把它弄得太大,最后它没有达到我的意图。 但是我想我想要达到的目标是不可能的,就像@Quimby 解释的那样。

我真正想做的是一个调试助手(实际上是虚幻引擎),用于跟踪对象值,类似于这样的可包含 .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。

没有

必须解决的根本问题是确定模板变量是否已实例化。否则,在无限多的可能实例中搜索会很有趣。

C++ 不提供回答此类问题的工具,因为实现几乎是不可能的。主要是由于分开的编译和链接过程。 TL;DR; 可能是翻译单元 (TU) 还没有包含足够的信息,链接器来不及了,因为代码已经生成了。

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

链接器的工作是收集所有这些目标文件,解析导出和丢失的符号,包括删除 inline 定义的重复项,最后创建 executable/library.

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

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

#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';
}