2011-04-27 96 views
3

我想創建一個類,用戶可以在地圖中存儲不同類型的數據。我爲bool,int和std :: string創建了一個映射,並創建了模板函數,以便我不必爲每種類型重寫get和set函數。爲什麼std :: string不是模板常量參數的有效類型?

這裏是我的代碼minmal版本:

#include <map> 
#include <string> 
#include <stdexcept> 
#include <iostream> 

class Options { 
public: 
    template<class T> 
    void Set(const std::string& name, const T& value) { 
     GetMap<T>()[name] = value; 
    } 
    template<class T> 
    T Get(const std::string& name) { 
     auto it = GetMap<T>().find(name); 
     if(it == GetMap<T>().end()) { 
      throw std::runtime_error(name + " not found"); 
     } 
     return it->second; 
    } 
private: 
    std::map<std::string, int> ints_; 
    std::map<std::string, std::string> strings_; 
    std::map<std::string, bool> bools_; 

    template<class T> 
    std::map<std::string, T>& GetMap(); 
    template<bool> 
    std::map<std::string, bool>& GetMap() { 
     return bools_; 
    } 
    template<std::string> // error 
    std::map<std::string, std::string>& GetMap() { 
     return strings_; 
    } 
    template<int> 
    std::map<std::string, int>& GetMap() { 
     return ints_; 
    } 
}; 

int main() { 
    Options o; 
    o.Set("test", 1234); 
    o.Set<std::string>("test2", "Hello World!"); 
    std::cout << o.Get<int>("test") << std::endl 
       << o.Get<std::string>("test2") << std::endl; 
} 

,我發現了以下錯誤:

error: 'struct std::basic_string<char>' is not a valid type for a template constant parameter 

但是,爲什麼?

+1

我認爲你的設計不夠好。存儲3張地圖不是個好主意。你可以在你的地圖中使用{int,bool,string}的'union'或者使用boost :: any或boost :: variant作爲值。 – 2011-04-27 09:09:42

+3

@Mihran Hovsepyan:'union'不是一個選項(在當前的標準中,'std :: string'不是POD類型,它將在即將到來的,但你需要標記它以適當地使用它) 。另一方面,'boost :: any'和'boost :: variant'都是有效的選項。 – 2011-04-27 09:58:02

+0

謝謝!我會研究boost :: any和boost :: variant :) – jhasse 2011-04-27 10:05:29

回答

6

兩點:

  • 專業化應該是類(重要),否則將無法編譯
  • 專業化的正確語法如下:

    //outside the class definition 
    
    template<> 
    std::map<std::string, bool>& Options::GetMap<bool>() { 
              //^^^^^^^^^ dont forget this! 
         return bools_; 
    } 
    template<> 
    std::map<std::string, std::string>& Options::GetMap<std::string>() { 
                //^^^^^^^^^ dont forget this! 
         return strings_; 
    } 
    template<> 
    std::map<std::string, int>& Options::GetMap<int>() { 
              //^^^^^^^^^ dont forget this! 
         return ints_; 
    } 
    
7

如果我理解正確,您正在嘗試專用功能模板GetMap()。但是你的語法不正確;你可能想要:

template<class T> 
std::map<std::string, T>& GetMap(); 

template<> 
std::map<std::string, bool>& GetMap<bool>() { 
    return bools_; 
} 

等等。

+0

此外,專業化應該在類之外(重要),否則它不會編譯。 – Nawaz 2011-04-27 09:12:26

+0

@Nawaz:啊,是的,這是一個很好的觀點。看起來,VS 2010允許這樣做,那就是我在做快速實驗的地方! – 2011-04-27 10:03:20

+0

VisualStudio不支持Two Phase Lookup,這會導致它接受各種通常誘人方便的(模板)代碼,這很不幸是錯誤的。 – 2011-04-27 11:47:14

相關問題