如何在没有<array>的情况下声明具有统一类型的元组?

时间:2016-12-08 22:32:44

标签: c++ c++11 tuples idioms stdarray

我想要一个我正在编写的函数来返回一个N foo s的元组,其值为N(N不是代码的一部分)。

如果它是C ++ 14,我可以绕过实际声明任何东西,只使用auto作为返回类型,但这在C ++ 11中不起作用。我不想使用-> auto decltype,因为这意味着很多的文字,我不妨写一下,例如std::tuple{foo, foo, foo, foo}

另一种选择是将返回类型设为std::array<foo, N>;这应该可行。但是,我想知道的是,如果我没有完全提到<array>,我实际上并不需要它的功能。

4 个答案:

答案 0 :(得分:4)

typedef struct {
    char **historyCommand;
    int usedSize;
    int maximumSize;
} HistoryArray;

void CreateHistoryArray(HistoryArray *HistoryArray) {
    HistoryArray->historyCommand = malloc(INITIAL_SIZE * sizeof(char *));
    HistoryArray->usedSize = 0;
    HistoryArray->maximumSize = INITIAL_SIZE;
}

void ExpandHistoryArray(HistoryArray *HistoryArray, int newSize) {
    HistoryArray->historyCommand = realloc(HistoryArray->historyCommand, newSize * sizeof(char *));
    HistoryArray->maximumSize = newSize;
}

void AddHistoryValue(HistoryArray *HistoryArray, char historyCommand[]) {
    historyCommand[HistoryArray->usedSize] = malloc(strlen(historyCommand) + 1);
    strcpy(HistoryArray->historyCommand[HistoryArray->usedSize], historyCommand);

    HistoryArray->usedSize++;

    if (HistoryArray->usedSize == HistoryArray->maximumSize) {
        ExpandHistoryArray(HistoryArray, HistoryArray->maximumSize * 2);
    }
}

void freeHistoryArray(HistoryArray *a) {
    for (int i = 0; i < a->usedSize; i++) {
        free a->historyCommand[i];
    }
    a->usedSize = 0;
    a->maximumSize = 2;
    a->historyCommand = realloc(a->historyCommand, a->maximumSize * sizeof(char *));
}

HistoryArray historyArray;

答案 1 :(得分:3)

使用integer_sequence [integer_seq.h]的外部实现,c ++ 11方法对c ++ 14进行样式设计可能如下所示:

#include <tuple>
#include <utility>
#include <iostream>
#include <initializer_list>
#include "integer_seq.h"

using namespace redi;


template <class T, std::size_t N, class = make_index_sequence<N>>
struct tuple_generator;

template <std::size_t, class T>
using typer = T;

template <class T, std::size_t N, std::size_t... Is>
struct tuple_generator<T, N, index_sequence<Is...>> {
    using type = std::tuple<typer<Is, T>...>;
};

int main() {
    static_assert(std::is_same<tuple_generator<int, 3>::type, std::tuple<int, int, int>>::value, "!");
}

[live demo]

答案 2 :(得分:2)

我要从@Smeeheey的回答中回答这个问题,回答我提出的另一个问题:C++ parameter pack, constrained to have instances of a single type?

关联是,你的问题与tuple没什么关系,真的,

  

如何重复多次重复包含相同类型的参数包?

最直截了当的答案是,使用std::make_index_sequence和包扩展:

#include <tuple>
#include <utility>

template <typename T, unsigned n>
struct repeat_tuple {
  template <unsigned>
  struct blah {
    using type = T;
  };

  template <typename IS>
  struct helper;

  template <unsigned ... Is>
  struct helper<std::integer_sequence<unsigned, Is...>> {
    using type = std::tuple<typename blah<Is>::type...>;
  };

  using type = typename helper<std::make_integer_sequence<unsigned, n>>::type;
};

template <typename T, unsigned n>
using repeat_tuple_t = typename repeat_tuple<T, n>::type;

static_assert(std::is_same<repeat_tuple_t<int, 3>, std::tuple<int, int, int>>::value, "");

int main() {}

这最终与W.F。的答案相同,但也许有点苛刻。编辑:我猜他在答案中回溯了C ++ 14的特征。

tuple_cat方法不同,此方法也适用于除元组之外的其他方法。

事实上,我猜std::tuple可能是模板模板参数......

:邪恶的眼睛:

答案 3 :(得分:-1)

常规功能无法实现这一点。

函数的返回类型是固定的,不能更改。具有不同类型的元组每个都是不同的类型,因此您不能拥有一个返回不同元组类型的函数。

示例:与tuple<int, int>

相比,tuple<int,int,int>是一种不同的类型

话虽如此,您可以使用函数模板执行此操作(make_shared以这种方式实现),调用程序在进行函数调用时显式指定返回的元组类型。我不认为这是好的可用性,因为元组是冗长的。

使用std :: array(或std :: vector)可能是更容易的路径。