【问题标题】:STL Metaprogramming - which types of my template class have been created at compile time?STL Metaprogramming - 我的模板类的哪些类型是在编译时创建的?
【发布时间】:2012-06-13 10:13:00
【问题描述】:

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

我有一个模板类,它基本上如下所示 - 它使用单例模式,因此一切都是静态的,我不是在寻找 cmets 来了解为什么我将密钥存储在一个集合中并使用字符串等,除非它实际上提供了解决方案。这门课还有一些内容,但这与问题无关。

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 的这个方面对我来说有点新,所以我很乐意阅读并尽可能多地学习,只要我确切知道我需要学习什么来设计解决方案。

【问题讨论】:

  • 您想维护所有键的全局列表吗?您也可以将其放入全局变量中,或者如果您愿意,也可以放入 MyClass 继承自的超类的静态成员。
  • “所有类型”是什么意思?我认为您问题的 那个 方面没有意义。您可以为所有原始类型显式实例化您的模板,并为所有用户定义的类型编写一个自注册帮助器类。

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


【解决方案1】:

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

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

【讨论】:

  • 是的,现在我想起来似乎有点明显 - 我想我太热衷于开始使用模板元编程,因此正在考虑过度设计解决问题的方法!
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    第二个答案:有一个解决方法。可以定义一个基类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&lt;T&gt;::instance();改成T* instance = MyClass&lt;T&gt;::privateInstance();

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-20
      • 2012-05-10
      • 2012-01-20
      • 1970-01-01
      • 2011-09-08
      • 2012-01-27
      相关资源
      最近更新 更多