2013-03-23 118 views
13

我正在寫一個類似於boost :: promote的促銷模板別名,但對於C++ 11。 這樣做的目的是在從varidic函數中檢索參數時避免警告。例如C++ 11類型特徵來區分枚舉類和常規枚舉

template <typename T> 
std::vector<T> MakeArgVectorV(int aArgCount, va_list aArgList) 
{ 
    std::vector<T> args; 
    while (aArgCount > 0) 
    { 
     args.push_back(static_cast<T>(va_arg(aArgList, Promote<T>))); 
     --aArgCount; 
    } 
    return args; 
} 

的促進模板別名促進以下默認參數晉升爲可變參數的類型: 1)一個整數,是小於一個int被提升爲int 2)浮子被提升到一倍

我的問題是,可以提升標準C++枚舉,但不推薦C++ 11枚舉類(編譯器不會生成警告)。我想促進與常規枚舉一起工作,但忽略C++ 11枚舉類。

如何分辨我的Promote模板別名中的枚舉類和枚舉之間的區別?

+1

真正的問題是,您正在使用'va_arg's而不是'std :: initializer_list'和/或variadic模板。 – Fanael 2013-03-23 11:50:58

+0

感謝您的提示,但我有va_list,因爲我正在使用C接口。 – Sam 2013-03-23 13:08:17

+0

@Sam:我的答案能解決您的問題嗎? – 2013-03-24 17:14:26

回答

21

這裏是一個可能的解決方案:

#include <type_traits> 

template<typename E> 
using is_scoped_enum = std::integral_constant< 
    bool, 
    std::is_enum<E>::value && !std::is_convertible<E, int>::value>; 

將該溶液利用之間的行爲的差作用域和段落的C++ 11標準的7.2/9指定的無作用域枚舉:

的枚舉器的值或非範圍枚舉類型的對象通過整數提升(4.5)轉換爲整數。 [...]請注意,這種隱式枚舉到int轉換不是爲範圍枚舉提供的。 [...]

這裏是你將如何使用它的演示:

這裏是一個live example

致謝:

感謝Daniel Frey您指出我之前的做法只會只要是operator +沒有用戶定義的超負荷工作。

+3

+1,但有一個洞穴:它只有在某些枚舉類「E」的作者有** not **定義了他自己的'operator +(int,E)'時才起作用。通過添加一個'void dummy(int)'並使用'decltype(dummy(std :: declval ()))'來修復它。 – 2013-03-23 11:52:58

+1

@DanielFrey:好點。實際上,我可以使用不同的運算符,比如'^',以便不太可能干擾用戶定義的運算符過載 – 2013-03-23 11:55:17

+1

@AndyProwl:或者調用帶有int的函數。 – Fanael 2013-03-23 11:56:48