2016-08-08 3 views
8

В стандарте C++ 11 есть шаблон std::conditional<> для выбора типа с помощью некоторого логического состояния во время компилятора. Как выполнить ту же операцию, но для выбора значения init для инициализации переменных? Подобно type a = (exp) ? first_value : second_value;.Как выполнить инициализацию условной переменной во время компиляции?

Я использую свой шаблон:

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

Но он может быть использован только для типов POD: int a = conditional_initialize<true>(1, 2);. Для инициализации массива этот шаблон скомпилирован с ошибкой. Неправильный пример компиляции: сообщение int a[] = conditional_initialize<true>({1, 2}, {3,4,5});

Ошибка: no matching function for call to 'conditional_initialize(<brace-enclosed initializer list>, <brace-enclosed initializer list>)';

Кто может помочь мне с шаблоном?

+2

@AndyG Нет, это 'станд :: initializer_list alexeykuzmin0

+0

' 'Int А [] = conditional_initialize ({1, 2}, {3,4,5});' Это не может работать, вы не можете копировать или перемещать построить встроенные массивы. –

+2

@ alexeykuzmin0 это было бы действительно, но, к сожалению, [шаблоны не могут вывести 'std :: initializer_list'] (http://stackoverflow.com/a/12431810/3233393). – Quentin

ответ

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

это дает вам:

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

, которая близка.

В целом, конструкции {} не являются выражениями, они не могут быть переправлены через какой-либо механизм через другую переменную.

Мы также можем получить:

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

с немного больше работы.

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

Я не делал эти constexpr, потому что лень.

+0

** Yakk **, как насчет такого шаблона - http://cpp.sh/6swua? – 23W

+0

@ 23W - это не только мой 'cond_init' и ручной' make_array' случай с небольшими изменениями? Я был ленив в том, что я не проверял «std :: tie» и тому подобное, достаточно «constexpr» для любой версии C++, которую вы использовали. – Yakk

+0

Да, это так.Это модификация вашего кода для единого подхода для простых типов и массив std C++ (которые являются разными типами для разных размеров). – 23W

Смежные вопросы