2013-03-23 13 views
13

Piszę alias szablonu promocji podobny do boost :: promot, ale do C++ 11. Celem tego jest uniknięcie ostrzeżeń podczas pobierania argumentów z funkcji zmiennych. na przykładCecha typu C++ 11 rozróżniająca klasę wyliczeń i wyliczenie regularne

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; 
} 

Promuj szablonu alias promuje rodzaj następujące promocji domyślnym argumentem dla zmiennej liczbie argumentów argumentów: 1) liczbę całkowitą, która jest mniejsza niż int jest promowany do int 2) pływak jest promowany podwoić

Mój problem polega na tym, że standardowe wyliczanie C++ może być promowane, ale klasa enum C++ 11 nie jest promowana (kompilator nie generuje ostrzeżenia). Chcę, aby Promote działał z regularnym wyliczaniem, ale ignoruje klasę enum C++ 11.

Jak odróżnić klasę wyliczeniową od wyliczenia w aliasie Promuj szablon?

+1

Prawdziwy problem polega na tym, że używasz 'va_arg's zamiast' std :: initializer_list' i/lub variadic templates. – Fanael

+0

Dzięki za napiwek, ale mam listę va_list, ponieważ pracuję z interfejsem C. – Sam

+0

@Sam: Czy moja odpowiedź rozwiązuje twój problem? –

Odpowiedz

21

tutaj jest możliwe rozwiązania

#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>; 

Rozwiązanie wykorzystuje różnicę w zachowaniu pomiędzy zawężona i unscoped wyliczenia określono w paragrafie 7.2/9 C++ 11 Standard:

The wartość modułu wyliczającego lub obiektu nieskrępowanego typu wyliczeniowego jest konwertowana na liczbę całkowitą przez integralną promocję (4.5). [...] Należy zauważyć, że ta domniemana konwersja enum int nie jest przewidziana dla wyliczenia o zakresie. [...]

Tutaj jest wykazanie w jaki sposób z niego korzystać:

A oto live example.

PODZIĘKOWANIA:

Dzięki Daniel Frey za wskazanie, że mój poprzedni podejście będzie działać tylko tak długo, jak nie ma zdefiniowanej przez użytkownika przeciążenie operator +.

+3

+1, ale jest jedna jaskinia-at: Działa tylko tak długo, jak autor jakiejś enum klasy 'E' ma ** nie ** zdefiniował swój własny' operator + (int, E) '. Napraw go, dodając 'void dummy (int)' i użyj 'decltype (dummy (std :: declval ()))'. –

+1

@DanielFrey: Dobra uwaga. Właściwie mógłbym użyć innego operatora, takiego jak '^', aby zmniejszyć prawdopodobieństwo ingerowania w zdefiniowane przez użytkownika przeciążenie operatora –

+1

@AndyProwl: lub wywołać funkcję, która przyjmuje 'int'. – Fanael

Powiązane problemy