如何在编译时查询一个constexpr的std::tuple?

20
在C++0x中,可以创建一个constexpr std::tuple,比如:
#include <tuple>
constexpr int i = 10;
constexpr float f = 2.4f;
constexpr double d = -10.4;
constexpr std::tuple<int, float, double> tup(i, f, d);

还可以在运行时查询std::tuple,例如通过

int i2 = std::get<0>(tup);

但是不可能在编译时查询它,例如:

constexpr int i2 = std::get<0>(tup);

最新的g++快照(2011-02-19)会抛出编译错误。

还有其他方法可以在编译时查询constexpr std::tuple吗?

如果没有,是否有概念上的原因导致不能查询它?

(我知道要避免使用std::tuple,例如改用boost::mpl或boost::fusion,但是不使用新标准中的tuple类似乎不太对...)

顺便问一句,有人知道为什么吗?

  constexpr std::tuple<int, float, double> tup(i, f, d);

编译通过,但是

  constexpr std::tuple<int, float, double> tup(10, 2.4f, -10.4);

不是吗?

非常感谢! - lars


在n3225.pdf中,只有默认构造函数被标记为constexpr。也许现在使用这个特性还为时过早? - UncleBens
4个回答

13

std::get没有被标记为constexpr,因此您无法在constexpr上下文中使用它来检索从tuple中的值,即使该元组本身是constexpr

不幸的是,std::tuple的实现是不透明的,因此您也无法编写自己的访问器。


谢谢。所以你的答案是“不,这是不可能的。”与此同时,我已经看了一下<tuple>,完全同意。这就引出了一个问题:为什么我们不能在编译时查询std::tuples呢?但是,这个问题可能更好地在我有关std::forward的constexpr性质的更广泛范围的问题中讨论。链接:https://dev59.com/G2435IYBdhLWcg3w-1Z_ - Lars
9
N3305 建议为 tuple::get 添加 constexpr - Dave Abrahams

3

现在,std::get<>是一个constexpr函数。如果我使用gcc c++ 11或更高版本,下面的代码就可以编译。

constexpr int i2 = std::get<0>(tup);
constexpr std::tuple<int, float, double> tup(10, 2.4f, -10.4);

此外,您可以使用make_index_sequence(c++14或更高版本)在编译时生成数字列表,并访问元组。

constexpr auto size = std::tuple_size<decltype(tup)>::value;
for_sequence(std::make_index_sequence<size>{}, [&](auto i){
        constexpr auto property = std::get<i>(tup);
        std::cout<<property<<std::endl;
});

template <typename T, T... S, typename F>
constexpr void for_sequence(std::integer_sequence<T, S...>, F&& f) {
    using unpack_t = int[];
    (void)unpack_t{(static_cast<void>(f(std::integral_constant<T, S>{})), 0)..., 0};
}

0

-2

我还没有使用过C++0x,但我认为std::get()是一个函数,而不是编译器可以直接解释的表达式。因此,在函数本身被编译后,它只有在运行时才有意义。


1
C++0x 添加了关键字 constexpr,它实际上强制编译器在编译时计算函数,例如 constexpr int add(int x, int y) { return x+y;},你可以这样写 constexpr int i = add(7, 13);,i 的值在编译时可用,例如在 static_assert(i == 20, "i correct"); 中。-- 所以我的问题是为什么 std::get 不是 constexpr? - Lars
constexpr 的想法是可以告诉编译器在参数也是 const 表达式的情况下计算函数调用的结果。 - UncleBens
这并不是我所找到的参考资料的理解。我的理解是,constexpr 可以定义返回常量表达式的内联函数(替代宏),但只有当该函数本身是 constexpr 时,它才能调用一个函数。 - Michael Scott Shappe
@Lars -- 我猜想的原因是,因为std::get<T>(arg)将被用于arg本身不会成为constexpr的情况下。 - Michael Scott Shappe
1
这也不是问题,因为当使用非constexpr参数调用时,constexpr将被静默丢弃。 - Lars

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接