c++17提供了if constexpr
,其中包含:
condition的值必须是类型为
getpid
的上下文转换的常量表达式。如果值为bool
,则丢弃statement-false(如果存在),否则将丢弃statement-true
有没有办法在true
语句中使用它?要在编译时展开循环吗?我希望能够做到这样的事情:
for
答案 0 :(得分:6)
有没有办法在for语句中使用它?要在编译时展开循环吗?我希望能够做这样的事情
我不会以这么简单的方式思考。
但是如果你能负担一个帮助函数,std::integer_sequence
和一个未使用的C风格整数数组的初始化,从C ++ 14开始你可以做如下的事情
#include <utility>
#include <iostream>
template <int ... Is>
void foo_helper (std::integer_sequence<int, Is...> const &)
{
using unused = int[];
(void)unused { 0, (std::cout << Is << std::endl, 0)... };
}
template <int T>
void foo ()
{ foo_helper(std::make_integer_sequence<int, T>{}); }
int main ()
{
foo<42>();
}
如果您可以使用C ++ 17,则可以避免使用unused
数组,并且使用折叠,foo_helper()
可以简单地编写如下
template <int ... Is>
void foo_helper (std::integer_sequence<int, Is...> const &)
{ ((std::cout << Is << std::endl), ...); }
答案 1 :(得分:4)
如果编译器知道循环限制,编译器将展开循环,如果它发现它有益。并非所有循环展开都是有益的!对于循环展开的好处,你不太可能比编译器做出更好的决定。
不需要constexpr for
(正如你所说的那样),因为constexpr if
是启用功能 - 你可能会在constexpr if
假分支内放置会导致程序格式错误的代码 - 这不是纯粹的优化。
Constexpr for
将是纯粹的优化(至少在您描述时,不计算循环执行0次的边缘情况),因此最好留给'as-if'优化规则。
答案 2 :(得分:2)
不是没有帮助代码。
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
template<std::size_t I>
using index_t = std::integral_constant<std::size_t, I>;
template<std::size_t...Is>
constexpr auto index_over( std::index_sequence<Is...> ) noexcept(true) {
return [](auto&& f)
RETURNS( decltype(f)(f)( index_t<Is>{}... ) );
}
template<std::size_t N>
constexpr auto index_upto( index_t<N> ={} ) noexcept(true) {
return index_over( std::make_index_sequence<N>{} );
}
template<class F>
constexpr auto foreacher( F&& f ) {
return [&f](auto&&...args) noexcept( noexcept(f(args))&&... ) {
((void)(f(args)),...);
};
}
这是我们的管道。
template<int T>
void foo() {
index_upto<T>()(
foreacher([](auto I){
std::cout << I << "\n";
})
);
}
每个步骤都有值的编译时循环。
或者我们可以隐藏细节:
template<std::size_t start, std::size_t length, std::size_t step=1, class F>
constexpr void for_each( F&& f, index_t<start> ={}, index_t<length> ={}, index_t<step> ={} ) {
index_upto<length/step>()(
foreacher([&](auto I){
f( index_t<(I*step)+start>{} );
})
);
}
然后我们得到:
for_each<0, T>([](auto I) {
std::cout << I << "\n";
});
或
for_each([](auto I) {
std::cout << I << "\n";
}, index_t<0>{}, index_t<T>{});
这可以通过用户定义的文字和模板变量进一步改进:
template<std::size_t I>
constexpr index_t<I> index{};
template<char...cs>
constexpr auto operator""_idx() {
return index< parse_value(cs...) >;
}
其中parse_value
是constexpr
函数,它接受char...
序列并生成无符号整数表示。