2016-08-08 15 views
8

Standard C++ 11 ma szablon std::conditional<> dla wyboru typu przez pewien warunek boolowski w czasie kompilacji. Jak wykonać tę samą operację, ale w celu wybrania wartości początkowej dla inicjalizacji zmiennej? Podobny do type a = (exp) ? first_value : second_value;.Jak wykonać inicjowanie zmiennej warunkowej w czasie kompilacji?

używam szablonu:

template<bool B, typename T> 
inline constexpr T&& conditional_initialize(T&& i1, T&& i2) { 
    return B ? std::move(i1) : std::move(i2); 
} 

Ale to może być stosowane tylko dla typów POD: int a = conditional_initialize<true>(1, 2);. Do inicjalizacji macierzy ten szablon jest kompilowany z błędem. Źle przykład kompilacji: Komunikat int a[] = conditional_initialize<true>({1, 2}, {3,4,5});

Błąd: no matching function for call to 'conditional_initialize(<brace-enclosed initializer list>, <brace-enclosed initializer list>)';

Kto może mi pomóc w szablonie?

+2

@AndyG Nie, to 'std :: initializer_list ' – alexeykuzmin0

+0

'int a [] = conditional_initialize ({1, 2}, {3,4,5});' To nie może pracować, nie można skopiować lub przenieść skonstruuj wbudowane tablice. –

+2

@ alexeykuzmin0 byłoby rzeczywiście, ale niestety [szablony nie mogą wywnioskować 'std :: initializer_list'] (http://stackoverflow.com/a/12431810/3233393). – Quentin

Odpowiedz

8
template<class T, std::size_t N, std::size_t M, bool b> 
std::array<T, b?N:M> 
conditional_array(std::array<T, N>&& lhs, std::array<T, M>&& rhs) { 
    return std::move(std::get<b?0:1>(std::tie(lhs, rhs))); 
} 

to daje:

auto a = conditional_array<int,2,3,true>({{1, 2}}, {{3,4,5}}); 

który jest blisko.

Ogólnie rzecz biorąc, konstrukcje {} nie są wyrażeniami, nie mogą być perfekcyjnie przekazywane za pośrednictwem dowolnego mechanizmu za pośrednictwem innej zmiennej.

Możemy również uzyskać:

auto a = cond_init<true>(make_array(1,2), make_array(3,4,5)); 

z nieco więcej pracy.

template<bool Test, class A, class B> 
std::conditional_t<Test,A,B> 
cond_init(A a, B b) { 
    return std::move(std::get<Test?0:1>(std::tie(a,b))); 
} 
template<class T0, class...Ts> 
std::array< std::decay_t<T0>, sizeof...(Ts)+1 > 
make_array(T0&& t0, Ts&&...ts) { 
    return {{std::forward<T0>(t0), std::forward<Ts>(ts)...}}; 
} 

Nie zrobiłem tych constexpr, ponieważ są leniwe.

+0

** Yakk **, jak o takim szablonie - http://cpp.sh/6swua? – 23W

+0

@ 23W to nie tylko moja sprawa 'cond_init' i instrukcja' make_array' z małymi zmianami? Byłem leniwy pod tym względem, że nie kontrolowałem 'std :: tie' i tym podobne są wystarczająco" constexpr "dla jakiejkolwiek wersji C++, której używałeś. – Yakk

+0

Tak, jest.Jest to modyfikacja twojego kodu dla pojedynczego podejścia dla prostych typów i C++ std array (które są różnymi typami dla różnych rozmiarów). – 23W

Powiązane problemy