23W 23W - 4 months ago 10
C++ Question

How to do the conditional variable initialization at compiler time?

C++11 standard have

std::conditional<>
template for the type selection by the some boolean condition at compiler time.
How to do the same operation but for select the init value for variable initialization? Similar to
type a = (exp) ? first_value : second_value;
.

I use my template:

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


But it can be used only for POD types:
int a = conditional_initialize<true>(1, 2);
.
For array initialization this template is compiled with error. Wrong compile example:
int a[] = conditional_initialize<true>({1, 2}, {3,4,5});



Error message: no matching function for call to 'conditional_initialize(<brace-enclosed initializer list>, <brace-enclosed initializer list>)';


Who can help me with template?

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

this gives you:

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

which is close.

In general, {} constructs are not expressions, they cannot be perfectly forwarded through any mechanism through another variable.

We can also get:

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

with a bit more work.

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

I didn't make these constexpr, because lazy.