cal*_*vin 4 c++ constexpr c++11 c++14
我写了这样的代码
#include <iostream>
using namespace std;
constexpr int getsum(int to){
int s = 0;
for(int i = 0; i < to; i++){
s += i;
}
return s;
}
int main() {
constexpr int s = getsum(10);
cout << s << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我知道它的工作原理是因为扩展了constexpr.然而,在这个问题为什么不是一个for-loop-a-compile-time-expression,作者给出了他的代码如下:
#include <iostream>
#include <tuple>
#include <utility>
constexpr auto multiple_return_values()
{
return std::make_tuple(3, 3.14, "pi");
}
template <typename T>
constexpr void foo(T t)
{
for (auto i = 0u; i < std::tuple_size<T>::value; ++i)
{
std::get<i>(t);
}
}
int main()
{
constexpr auto ret = multiple_return_values();
foo(ret);
}
Run Code Online (Sandbox Code Playgroud)
它不能由GCC5.1编译,但是,在用std::get<i>(t);没有指定模板参数的东西替换之后,他的代码确实有效.在根据这个问题阅读答案后,我发现他们的主要观点是constexpr for为编译器带来了麻烦,因此在运行时使用了for循环.所以它让我困惑,一方面for-loop是在运行时,另一方面,循环是在一个constexpr函数中,所以它必须在编译时计算,所以似乎有一个矛盾.我只是想知道我在哪里弄错了.
这实际上与constexpr函数是否需要能够在编译时运行tuple_size<T>::value无关(无论是否T来自constexpr对象,都是一个常量表达式).
std::get<>是一个函数模板,需要调用整型常量表达式.在这个循环中:
for (auto i = 0u; i < std::tuple_size<T>::value; ++i)
{
std::get<i>(t);
}
Run Code Online (Sandbox Code Playgroud)
i不是一个完整的常数表达式.它甚至不是一成不变的.i整个循环的变化和假设每一个值0来tuple_size<T>::value.虽然它看起来像它,但它不会调用具有不同值的函数i- 这每次调用不同的函数.目前对于这种迭代†没有语言支持,这与原始示例有很大不同,我们只是总结整数.
也就是说,在一种情况下,我们循环i并调用f(i),而在另一种情况下,我们循环i并调用f<i>().第二个比第一个有更多的先决条件.
†如果添加了这样的语言支持,可能是以constexpr for声明的形式,那么支持将constexpr无论如何都独立于功能.
您的函数需要在运行时和编译时都有效.因此,您的Variant i可以被视为运行时变量.如果函数在编译时执行,则该变量i是编译器运行时的一部分.因此int,constexpr函数int中的a与非constexpr函数中的a 规则相同.
你可以做的是创建自己的constexpr for循环:
template<typename F, std::size_t... S>
constexpr void static_for(F&& function, std::index_sequence<S...>) {
int unpack[] = {0,
void(function(std::integral_constant<std::size_t, S>{})), 0)...
};
(void) unpack;
}
template<std::size_t iterations, typename F>
constexpr void static_for(F&& function) {
static_for(std::forward<F>(function), std::make_index_sequence<iterations>());
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用static_for这样的:
static_for<std::tuple_size<T>::value>([&](auto index) {
std::get<index>(t);
});
Run Code Online (Sandbox Code Playgroud)
请注意,在C++ 17之前,lambda函数不能用于constexpr函数,因此您可以改为使用自己的仿函数:
template<typename T>
struct Iteration {
T& tuple;
constexpr Iteration(T& t) : tuple{t} {}
template<typename I>
constexpr void operator() (I index) const {
std::get<index>(tuple);
}
};
Run Code Online (Sandbox Code Playgroud)
现在你可以这样使用static_for:
static_for<std::tuple_size<T>::value>(Iteration{t});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3823 次 |
| 最近记录: |