【问题标题】:How to do the conditional variable initialization at compiler time?如何在编译时进行条件变量初始化?
【发布时间】:2016-08-08 23:09:44
【问题描述】:

C++11 标准有std::conditional<> 模板,用于在编译器时通过一些布尔条件进行类型选择。 除了选择变量初始化的初始值外,如何执行相同的操作?类似于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&lt;true&gt;(1, 2);。 对于数组初始化,此模板编译时出错。错误编译示例:int a[] = conditional_initialize&lt;true&gt;({1, 2}, {3,4,5});

错误信息:no matching function for call to 'conditional_initialize(<brace-enclosed initializer list>, <brace-enclosed initializer list>)';

谁能帮我做模板?

【问题讨论】:

  • @AndyG 不,是std::initializer_list&lt;int&gt;
  • int a[] = conditional_initialize&lt;true&gt;({1, 2}, {3,4,5}); 这不起作用,您不能复制或移动构造内置数组。
  • @alexeykuzmin0 确实是这样,但不幸的是templates cannot deduce std::initializer_list
  • 首先,int[] 是 POD 类型。其次,您不能从initializer_list&lt;int&gt; 初始化int a[],这几乎是您希望{1,2} 在该调用中推断出的最好的事情。 {} 构造不是表达式,因此它们不能完美地存储在类型变量或参数中。它们可用于构造类型化存储,但类型化存储与{} 不同。这是“完美”转发的失败之一。
  • @23W 因为正如他所说,您无法使用std::initializer_list 初始化内置数组。一方面,内置数组需要在编译时知道它的长度,std::initializer_list 会隐藏该信息直到运行时。

标签: c++ c++11


【解决方案1】:
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,因为懒惰。

【讨论】:

  • @23W 不只是我的cond_init 和手动make_array 的小改动吗?我很懒惰,因为我没有审核 std::tie 之类的,对于您使用的任何版本的 C++,constexpr 都足够了。
  • 是的。它是针对简单类型和 c++ std 数组(针对不同大小的不同类型)的单一方法修改您的代码。
猜你喜欢
  • 1970-01-01
  • 2021-04-22
  • 1970-01-01
  • 2019-05-17
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多