STL元编程 - 在编译时创建了哪些类型的模板类?

时间:2012-06-13 10:13:00

标签: c++ stl metaprogramming template-meta-programming

首先道歉,我不确定我的问题标题是否准确地解释了我的要求 - 我已经浏览了谷歌,但我不确定我的搜索查询中需要哪些术语,所以答案可能就在那里(甚至在StackOverflow上)。

我有一个模板化的类,它基本上如下所示 - 它使用Singleton模式,因此一切都是静态的,我不是在寻找关于为什么我将键存储在一个集合中并使用字符串等的注释,除非它实际上提供了解决方案。课堂上还有一点,但这与问题无关。

template<typename T>
class MyClass 
{
private:
  //Constructor and other bits and peices you don't need to know about
  static std::set<std::string> StoredKeys;
public:
  static bool GetValue(T &Value, std::string &Key)
  {
    //implementation
  }

  static SetValue(const T Value, std::string &Key)
  {
    //implementation
    StoredKeys.Insert(Key);
  }

  static KeyList GetKeys()
  {
    return KeyList(StoredKeys);
  }
};

稍后在应用程序的其他部分中,我想获得所有值的所有键 - 无论类型如何。

虽然我相当有信心,目前只有3或4种类型在课堂上使用,所以我可以这样写:

KeyList Keys = MyClass<bool>::GetKeys();
Keys += MyClass<double>::GetKeys();
Keys += MyClass<char>::GetKeys();

每次使用新类型时都需要更新。如果没有在任何地方使用它,它也有实例化类的缺点。

我认为(再次我可能是错的)元编程就是这里的答案,某种宏可能吗?

我们正在使用boost,所以我猜这个MPL库在这里有用吗?

STL的这个方面对我来说有点新鲜,所以我很乐意尽可能多地阅读和学习,只要我确切知道我需要学习什么来设计解决方案。< / p>

3 个答案:

答案 0 :(得分:0)

StoredKeys移动到非模板基类class MyClassBase中,或将AllStoredKeys静态成员添加到非模板基类。

或者,创建一个从SetValue调用的静态init方法,该方法将指向StoredKeys的指针添加到静态列表中。

答案 1 :(得分:0)

没有魔力。如果您需要枚举用于在程序中实例化MyClass的所有类型,那么您必须在某处明确枚举它们。不知何故。并且您必须在更改时手动更新列表。

使用模板元编程,您需要手动更新的地方数量可以减少到一个,但您确实需要一个地方。

幸运的是,在这个特定问题中,您不需要需要来枚举所有类型。您只需将所有键存储在一组中,而不是将它们分成几组。您可以为MyClass创建一个通用的非模板库,并在那里添加static std::set<std::string> StoredKeys(如果在不同类型的特定集合中可能存在相同的键,则可能使其成为multiset。< / p>

答案 2 :(得分:0)

第一个回答:它不可能! 模板类实际上并没有共同的“泛型”(比如在java中),而是一个与彼此没有任何关系的单独的类。

第二个回答:Theres是一个解决方法。可以定义基类MyClassBase,它定义所有模板化子类共享的属性。问题是你在这里有一个单例模式,这可能会使情况更加复杂。我认为解决方案可能如下所示:

class MyClassBase {
  static std::vector<MyClassBase*> childs;

  static KeyList getAllKeys(){
       //iterate over childs here and call ->GetKeys
  }

  virtual KeyList GetKeys() = 0;

  template<typename T>
  static T* instance() {
     T* instance = MyClass<T>::instance();
     if(std::find(childs.begin(), childs.end(), instance) != childs.end()){
       childs.push_back(instance);
     }
     return instance;
  }
};

请原谅我任何语法错误;我只是在Stackoverflow编辑器中键入它,但我认为它应该清楚我的观点。

修改 我刚刚看到我将子类的单例方法命名为instance()。这可能行不通。给它一些其他名称,如privateInstance()左右。然后,您必须将T* instance = MyClass<T>::instance();更改为T* instance = MyClass<T>::privateInstance();