2010-09-03 77 views
0

我的類的成員方法之一是作爲枚舉類型的參數:它爲不同的枚舉產生不同的副作用。我想知道是否有可能使用模板作爲一個查找表,兩個可能的解決方案,到了我的心,但他們都不似乎工作:具有不同修飾類型的實例化模板

//// 1 //// 

class A { 

    public: 

    enum AEnum : uint8_t { first, second, ... }; 

    private: 

    template<AEnum N, typename T> 
    struct impl { 
     static void do_sth(T t) { ... }; 
    }; 

    template<typename T> 
    struct impl<first, T> { 
     static void do_sth(T t) { ... }; 
    }; 

    public: 


    template<typename T> 
    void do_sth(AEnum e, T t) { 
     impl<e, T>::do_sth(t); 
    } 

} 

//// 2 //// 

class A { 

    public: 

    enum AEnum : uint8_t { first, second, ... }; 

    private: 

    template<typename T_enum, typename T> 
    struct impl { 
     static void do_sth(T t) { ... }; 
    }; 

    template<typename T> 
    struct impl<uint8_t[2], T> { // A::first 
     static void do_sth(T t) { ... }; 
    }; 

    public: 


    template<typename T> 
    void do_sth(AEnum e, T t) { 
     impl<uint8_t[static_cast<uint8_t>(e) + 1u], T>::do_sth(t); 
    } 

} 

是不是真的壞主意,這樣的代碼呢?

@Oli查爾斯沃思

有什麼不對switch語句?

do_sth的第二個參數(T)的受支持類型隨e的值而變化,例如, A :: first支持積分和A :: second STL容器,例如:

template<typename T> 
    void do_sth(AEnum e, T t) { 
     switch(e) { 
      case first: 
       std::cout << &t << std::endl; 
       break; 
      case second: 
       std::cout << t.data() << std::endl; 
       break; 
      default: 
       break; 
    } 

A a; 
a.do_sth(A::first, 0); 
+0

所以,如果e在運行時是第二,t是int,會發生什麼?似乎任何選擇都可以在編譯時發生,在這種情況下,根本不清楚枚舉是什麼。 – UncleBens 2010-09-03 23:23:44

+0

t在運行時不可能是int類型的,因爲它甚至不會編譯。我發現在相關的sfinae,認爲它應該做的伎倆。 – erjot 2010-09-04 11:25:48

回答

2

你必須讓AEnum精氨酸模板參數do_sth:


template<AEnum e, typename T> 
    void do_sth(T t) { ... } 

......並把它作爲a.do_sth<A::first>(0)。或者,您可以編寫單獨的函數(do_sth_integral,do_sth_container,...),或者如果對於特定的T只有一個正確的操作過程,則使用元編程爲給定的T推導「正確的」枚舉值/超載技巧。

例如,這是一種編寫兩個函數的方法,例如,檢測數值類型和容器類型:


//The extra dummy argument is invalid for types without a nested 
//"iterator" typedef 
template<typename T> 
void do_sth(T t, typename T::iterator * = 0) 
{ 
    //container type code 
} 

//The dummy arg is invalid for types without a 
//std::numeric_limits specialization 
template<typename T> 
void do_sth(T t, 
typename boost::enable_if_c<std::numeric_limits<T>::is_specialized>::type * = 0) 
{ 
    //numeric type code 
} 

當然,如果你通過它有一個迭代的typedef和numeric_limits專業化,或既沒有一件T這將失敗。

如果對於一個特定的T只有一個明智的行爲,並且很難正確地猜測哪個重載應該用於未知的T,那麼你可以使用一個traits類,用戶必須明確地專門化,或者只需要用戶專注於「impl」或調度類。

你不能寫,做類似3.data(),即使程序運行時的代碼路徑不調用的函數。編譯器不知道它永遠不會被調用,在任何情況下,它都會以導致診斷錯誤所需的方式違反語言的類型系統。

1

是的,你編碼的東西沒有任何意義。模板實例化在編譯器時解析,而顯然e的值僅在運行時才知道。

switch語句有什麼問題?