3

以下最小示例编译为g++ -std=c++11 -Wall tuple.cpp -o tuple

#include <tuple>
#include <iostream>

template<int i>
char get_elem_i(std::tuple<char, char> t)
{
    return std::get<i>(t);
}

int main()
{
    std::tuple<char, char> t('H','i');
    char c = get_elem_i<0>(t);
    std::cout << "The char is: " << c << std::endl;
}

现在,我不想使用指定索引的模板(确切原因:我有自动推导出的模板,我不想全部指定它们)。所以我的第一次尝试是:

char get_elem_i(int i, std::tuple<char, char> t)
{
    return std::get<i>(t);
}

我知道这无法编译。有没有办法保证编译器i在编译时就知道?也许是这样的?

char get_elem_i(compile_time_known int i, std::tuple<char, char> t)
4

2 回答 2

5

您可以使用 astd::array而不是 a std::tuple。在给出的示例中,元组的成员都具有相同的类型。

所以,我们可以这样做:

char get_elem_i(int i, std::array<char, 2> t)
{
    return t[i];
}

这是您给出的示例的一个轻微变体,以说明为什么在一般情况下不能直接实现:

???? get_elem_i(int i, std::tuple<char, struct foo, class bar> t) {
    return std::get<i>(t);
}

该函数的返回类型是什么?char? struct foo?


你总是可以写一个这样的函数:

char get_elem_i(int i, std::tuple<char, char> t) {
    switch (i) {
        case 0: return std::get<0>(t);
        case 1: return std::get<1>(t);
    }

    assert(false);
}
于 2013-05-07T17:27:00.110 回答
1

i如果您可以在编译时知道 的值,那么您可以i通过将您的逻辑包装iconstexpr.

例如:

#include <tuple>
#include <iostream>

constexpr int compile_time_known_i(int input) { return input / 3; }

template<int i>
char get_elem_i(std::tuple<char, char> t)
{
    return std::get<i>(t);
}

int main()
{
    std::tuple<char, char> t('H','i');
    char c = get_elem_i<0>(t);
    char d = get_elem_i<compile_time_known_i(3)>(t);
    std::cout << "The char is: " << c << " " << d <<  std::endl;
}

鉴于您i的 ' 可以在编译时知道,这可能有助于清理事情(尽管这有多大意义取决于您的用例)。

如果它是传递您所追求的参数的语法,您可以使用预处理器来实现这一点 - 具有一些可选的type_traits安全性。

#include <tuple>
#include <iostream>
#include <type_traits>

#define get_elem_i_ct(i, t)                                                                \
    std::get<i>(t);                                                                        \
    static_assert(std::is_integral<decltype(i)>::value, #i " must be an integral type");   \
    static_assert(std::is_same<decltype(t), std::tuple<char, char>>::value, #t " must be a tuple");

int main()
{
    std::tuple<char, char> t('H','i');
    char c = get_elem_i_ct(0, t)
    char d = get_elem_i_ct(1, t)
    std::cout << "The char is: " << c << " " << d <<  std::endl;
}

尽管这达到了规定的语法要求,但我不建议在愤怒中使用这种方法 - 几乎可以肯定,对于您的实际问题有更好的解决方案。

于 2013-05-07T17:43:24.087 回答