簡體   English   中英

成員函數的部分專業化

[英]Partial specialization of member functions

我在模板專業化方面遇到問題。 下面是兩個類,AbstractSetting(父級)和Setting(子級)。 (AbstractSetting可能並不重要,但出於上下文考慮,我將其包括在內。)

此代碼的最終目標是創建一個容器,以容納各種不同類型的INI設置-字符串,整數,枚舉等(數據類型),可以用枚舉(IndexType)進行引用。 在不同的上下文(主游戲,測試套件,服務器等)中可能會有不同的索引枚舉。

我正在嘗試創建一系列fromString方法,這些方法在傳遞字符串時返回DataType對象(我的模板參數之一)。

顯示的代碼將編譯但不會鏈接。

如果我取消注釋斷言,它將鏈接,但不會調用任何專業化,並且斷言將在每次對fromString的每次調用時觸發,而與參數無關。

我該如何進行這項工作?

請注意,U32,S32等是int類型。

template <class IndexType>
class AbstractSetting
{
private:
   IndexType mName;     // Value we use to look this item up
   string mIniKey;      // INI key
   string mIniSection;  // INI section
   string mComment;

public:
   // Constructor
   AbstractSetting(IndexType name, const string &key, 
                   const string &section, const string &comment):
      mIniKey(key), 
      mIniSection(section), 
      mComment(comment)
   {
      mName = name;
   }

   ~AbstractSetting() { /* Do nothing */ }      // Destructor

   IndexType getName()    const { return mName; }
   string    getKey()     const { return mIniKey; }
   string    getSection() const { return mIniSection; }
   string    getComment() const { return mComment; }

   virtual void setValFromString(const string &value) = 0;

   virtual string getValueString() const = 0;         // Returns val as str
   virtual string getDefaultValueString() const = 0;  // Returns def val as str
};


////////////////////////////////////////
////////////////////////////////////////

template <class DataType, class IndexType>
class Setting : public AbstractSetting<IndexType>
{
   typedef AbstractSetting Parent;

private:
   DataType mDefaultValue;
   DataType mValue;

public:
   Setting(IndexType name, const DataType &defaultValue, const string &iniKey, 
           const string &iniSection, const string &comment):
      Parent(name, iniKey, iniSection, comment),
      mDefaultValue(defaultValue),
      mValue(defaultValue)
   {
      // Do nothing
   }


   ~Setting() { /* Do nothing */ }

   // Templated declaration
   DataType fromString(const string &val) ; //{ Assert(false, "Specialize me!"); }

   // Specializations
   template<string *> string             
   fromString(const string &val) { return val; }

   template<S32 *> S32                
   fromString(const string &val) { return atoi(val.c_str()); }

   template<U32 *> 
   U32 fromString(const string &val) { return atoi(val.c_str()); }

   template<U16 *> 
   U16 fromString(const string &val) { return atoi(val.c_str()); }

   template<DisplayMode *> 
   DisplayMode fromString(const string &val) { return stringToDisplayMode(val); }

   template<YesNo *> 
   YesNo fromString(const string &val) { return stringToYesNo(val); }

   template<RelAbs *> 
   RelAbs fromString(const string &val) { return stringToRelAbs(val); }

   template<ColorEntryMode *> 
   ColorEntryMode fromString(const string &val) { return stringToColorEntryMode(val); }

   template<GoalZoneFlashStyle *> 
   GoalZoneFlashStyle fromString(const string &val) { return stringToGoalZoneFlashStyle(val); }

   template<Color *> 
   Color fromString(const string &val) { return Color::iniValToColor(val); }


   void   setValue(const DataType &value)       { mValue = value;                 }

   DataType getValue() const                    { return mValue;                  }
   string getValueString() const                { return toString(mValue);        }
   string getDefaultValueString() const         { return toString(mDefaultValue); }

   void   setValFromString(const string &value) { setValue(fromString(value));    }
};

我找到了解決方案!

由於成員函數似乎不能部分地專門化,因此我通過創建一個不使用IndexType參數的新類解決了該問題。

class Evaluator
{
public:
  template <class DataType> DataType fromString(const string &val);
};

在.cpp文件中,我添加了:

// Templated default - needs to be overriden
template<class DataType> DataType
Evaluator::fromString(const string &val) { 
    Assert(false, "Specialize me!"); 
    return DataType(); 
}

// Specializations.
// NOTE: All template specializations must be declared in the namespace scope to be
// C++ compliant.  Shame on Visual Studio!
template<> string             
Evaluator::fromString(const string &val) { return val; }

template<> S32                
Evaluator::fromString(const string &val) { return atoi(val.c_str()); }

template<> U32                
Evaluator::fromString(const string &val) { return atoi(val.c_str()); }

template<> U16                
Evaluator::fromString(const string &val) { return atoi(val.c_str()); }

template<> DisplayMode        
Evaluator::fromString(const string &val) { return stringToDisplayMode(val); }

template<> YesNo              
Evaluator::fromString(const string &val) { return stringToYesNo(val); }

template<> RelAbs             
Evaluator::fromString(const string &val) { return stringToRelAbs(val); }

template<> ColorEntryMode     
Evaluator::fromString(const string &val) { return stringToColorEntryMode(val); }

template<> GoalZoneFlashStyle 
Evaluator::fromString(const string &val) { return stringToGoalZoneFlashStyle(val); }

template<> Color              
Evaluator::fromString(const string &val) { return Color::iniValToColor(val); }

然后,在Setting類中,我將此調用替換為類似的代碼塊:

DataType fromString(const string &val) { 
    return mEvaluator.fromString<DataType>(val); 
}

這似乎工作得很好,並且可讀性很強。

如果有興趣的人,可以在下面的鏈接上找到完整的代碼,經過更全面的測試和簽入。

https://code.google.com/p/bitfighter/source/browse/zap/Settings.h

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM