如何迭代元组(使用C++ 11)?我尝试了以下方法:
for(int i=0; i<std::tuple_size<T...>::value; ++i)
std::get<i>(my_tuple).do_sth();
Run Code Online (Sandbox Code Playgroud)
但这不起作用:
错误1:抱歉,未实现:无法将"Listener ..."扩展为固定长度的参数列表.
错误2:我不能出现在常量表达式中.
那么,我如何正确迭代元组的元素?
正如标题所说,
一个典型的答案是:
允许任何和所有代码转换不会改变程序的可观察行为的规则
我们会不时地从某些实现中获取行为,这些行为归因于此规则.好多次错了.那么,这个规则究竟是什么呢.标准没有明确地将此规则作为一个部分或段落提及,那么究竟什么属于这条规则的范围?对我来说,这似乎是一个灰色区域,标准没有详细定义.有人可以根据标准的参考资料详细说明细节.
注意:将其标记为C和C++,因为它与两种语言都相关.
您可能知道,C++ 11引入了constexpr关键字.
C++ 11引入了关键字constexpr,它允许用户保证函数或对象构造函数是编译时常量.[...]这允许编译器理解并验证[函数名称]是编译时常量.
我的问题是为什么对可以声明的函数的形式有严格的限制.我理解保证功能是纯粹的愿望,但考虑到这一点:
在函数上使用constexpr会对函数的作用施加一些限制.首先,该函数必须具有非void返回类型.其次,函数体不能声明变量或定义新类型.第三,正文可能只包含声明,空语句和单个return语句.必须存在参数值,以便在参数替换后,return语句中的表达式生成常量表达式.
这意味着这个纯函数是非法的:
constexpr int maybeInCppC1Y(int a, int b)
{
if (a>0)
return a+b;
else
return a-b;
//can be written as return (a>0) ? (a+b):(a-b); but that isnt the point
}
Run Code Online (Sandbox Code Playgroud)
你也不能定义局部变量... :(所以我想知道这是一个设计决定,还是编译器吮吸来证明功能a是纯粹的?
我做了以下元组:
我想知道如何迭代它?有tupl_size(),但阅读文档,我没有得到如何利用它.我也搜索了SO,但问题似乎就在附近Boost::tuple.
auto some = make_tuple("I am good", 255, 2.1);
Run Code Online (Sandbox Code Playgroud) 我一直在乱搞SVN构建的clang来试验放松的规则constexpr.我之前无法确定的一件事是,是否可以在constexpr函数中在编译时循环遍历元组内的元素.
因为我没有要测试的符合C++ 14的标准库,所以我准备了以下等效测试:
template<int N>
constexpr int foo() {
return N;
}
constexpr int getSum() {
auto sum = 0;
for (auto i = 0; i < 10; ++i) {
sum += foo<i>();
}
return sum;
}
constexpr auto sum = getSum();
Run Code Online (Sandbox Code Playgroud)
这里有趣的部分是foo<i>().在非constexpr函数中,我希望它无法编译,因为您根本无法使用运行时int来生成模板的编译时实例化.constexpr但是,因为这是一个功能,我怀疑这是否可行.特别是,该值在编译时是已知的,即使它允许变异.
我知道以下代码将编译:
constexpr auto nValue = 2;
foo<nValue>();
Run Code Online (Sandbox Code Playgroud)
在SVN clang中,我的第一个例子没有:
test2.cpp:19:12: error: no matching function for call to 'foo'
sum += foo();
^~~~~~
test2.cpp:11:15: note: candidate template ignored: invalid explicitly-specified … 如何使用变量使用std :: get <>索引到元组?我有以下代码:
#include <iostream>
#include <tuple>
using namespace std;
int main() {
tuple<int, int> data(5, 10);
for (int i=0; i<2; i++) {
cout << "#" << i+1 << ":" << get<i>(data) << endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它失败并出现以下编译器错误:
prog.cpp: In function 'int main()':
prog.cpp:10:39: error: the value of 'i' is not usable in a constant expression
cout << "#" << i+1 << ":" << get<i>(data) << endl;
^
prog.cpp:9:11: note: 'int i' is not const
for …Run Code Online (Sandbox Code Playgroud) 我写了这样的代码
#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 < …Run Code Online (Sandbox Code Playgroud) for (int i = 0; i < 5; ++i) {
std::get<i>(tuple);
}
Run Code Online (Sandbox Code Playgroud)
这不会编译,因为i不是编译时常量。关于如何迭代 std::tuple 的元素?和其他帖子我看到了递归或使用的答案std::apply,但那些失去了索引控制。我也不想仅仅把自己限制在std::tuple。
每当我必须在编译时循环某些内容时,我都必须停下来思考并做一些奇怪的事情,特别是当我尝试实现非标准迭代(例如反向、自定义增量)或在同一语句(例如std::get<i>(tuple) * std::get<i + 1>(tuple).
对于c++20,我们能得到的最接近 a 的是什么constexpr for (int i = 0; i < 5; ++i)?
我无法通过hana::for_each迭代元组来找到访问真实对象的方法.
struct A {
std::string name;
}
struct B {
std::string name;
}
using type_t = decltype(boost::hana::tuple_t<A, B>);
type_t names;
boost::hana::for_each(names, [&](const auto& a) {
std::cout << a.name << std::endl;
});
Run Code Online (Sandbox Code Playgroud)
类型a似乎是hana::tuple_impl<...>并且似乎不可转换为其基础类型decltype(std::decay_t<a>)::type.
我基本上想要迭代一个具有相同接口但包含不同值的模板化对象(容器)列表.实现这一目标的更好方法是受欢迎的
在下面的代码中,我在 VS2017 中收到“错误 C3615:constexpr 函数 'to_array' 无法导致常量表达式”编译器错误:
#include <stdio.h>
#include <array>
template <typename T>
static constexpr std::array<std::uint8_t, sizeof(T)> to_array(T value)
{
std::array<std::uint8_t, sizeof(T)> result {};
for (std::size_t i{ sizeof(T) }; i != 0 ; --i)
{
result[i - 1] = static_cast<uint8_t>(value >> ((sizeof(T) - i) * 8));
}
return result;
}
int main()
{
constexpr uint64_t sample = UINT64_C(0xab28ecb46814fe75);
//error C3615: constexpr function 'to_array' cannot result in a constant expression
constexpr auto a = to_array(sample);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果理论上std::array …