Функция, которая может принимать массивы с разными размерами - PullRequest
0 голосов
/ 07 июня 2018

Есть ли способ создать одну функцию, которая может принимать любое измерение вектора без перегрузки?

В настоящее время у меня есть,

someFunction(vector<int> a)
someFunction(vector<vector<int> > a)
someFunction(vector<vector<vector<int> > > a)

Однако, возможно ли иметьфункция:

singleFunction(<n-dimension vector>)
{
    // Get dimension of array/vector
}

Ответы [ 5 ]

0 голосов
/ 07 июня 2018

С помощью C++17 вы можете написать довольно простое решение:

template<typename T >
constexpr int func(){
  if constexpr (is_vector<typename T::value_type>::value )
   return 1+func<typename T::value_type>();
  return 1;
}

int main() {
    cout<< func<vector<vector<vector<vector<vector<int>>>>>>() <<endl;
    return 0;
}

, которое возвращает 5, как и ожидалось.

Вам необходимо определить is_vector следующим образом:

template<class T>
struct is_vector{
     static bool const value = false;   
};
template<class T>
struct is_vector<std::vector<T> > {
  static bool const value = true;
};
0 голосов
/ 07 июня 2018

вы можете получить размер с этим кодом

#include <vector>
#include <iostream>

template<unsigned N, typename T>
struct meta {
    static unsigned func() {//terminale recursion case
        return N;
    }
};

template<unsigned N, typename T>
struct meta<N, std::vector<T> > {//mid recursion case
    static unsigned func() {
        return meta<N + 1, T>::func();
    }
};

template<typename T>
unsigned func(T) { //adapter to deduce the type
    return meta<0, T>::func();
}

int main() {
  std::cout << func(std::vector<std::vector<std::vector<int> > >()) << std::endl;
  std::cout << func(std::vector<int>()) << std::endl;
  std::cout << func(int()) << std::endl;
  std::cout << func(std::vector<std::vector<std::vector<std::vector<std::vector<std::vector<int> > > > > >()) << std::endl;
  return 0;
}

будет выводить

3
1
0
6
0 голосов
/ 07 июня 2018

Вы можете использовать рекурсивную шаблонную функцию

#include <iostream>
#include <vector>

void func(int el) {
  std::cout << el << std::endl;
}

template<typename T>
void func(std::vector<T> v) {
  for (const T& el : v) {
    func(el);
  }
}

int main() {
  std::vector<std::vector<int>> v {{1, 2}, {2, 3}};
  func(v);
  return 0;
}

Она вызывает ее сама для каждого элемента, пока не достигнет элементов типа int.

Чтобы получить измерение, вы можете использовать тот же шаблон:

#include <iostream>
#include <vector>

template<typename T>
int someFunction(std::vector<T> v, int dim = 1);

template<>
int someFunction(std::vector<int> v, int dim) {
  return dim;
}

template<typename T>
int someFunction(std::vector<T> v, int dim) {
  return someFunction(T(), dim + 1);
}

template<typename T>
void singleFunction(std::vector<T> v) {
  int dim(someFunction(v));
  std::cout << dim << std::endl;
  // Do something
}

int main() {
  std::vector<std::vector<std::vector<int>>> v {{{1, 0}, {2, 4}}, {{2, 2}, {3, 0}}};
  singleFunction(v);
  singleFunction(std::vector<std::vector<int>>());
  singleFunction(std::vector<int>());
  return 0;
}

Здесь он создает новый объект типа значения и вызывает себя, пока его тип значения не будет int.Каждый раз, когда он увеличивает размер.

0 голосов
/ 07 июня 2018

Возможно, вы могли бы попробовать этот подход, я думаю, что это именно то, что вы спрашиваете (принято из std :: rank ):

#include <iostream>
#include <vector>
#include <type_traits>

template<typename T>
struct vector_rank : public std::integral_constant<std::size_t, 0> {};

template<typename T>
struct vector_rank<std::vector<T>> : public std::integral_constant<std::size_t, vector_rank<T>::value + 1> {};

template<typename T>
size_t GetVectorRank(T)
{
    return vector_rank<T>::value;
}

int main()
{
    std::vector<std::vector<std::vector<std::vector<std::vector<int>>>>> v1;
    std::cout << GetVectorRank(v1) << std::endl;
    std::vector<std::vector<std::vector<int>>> v2;
    std::cout << GetVectorRank(v2) << std::endl;
    return 0;
}

Второй шаблон выбирается рекурсивно, покатип std::vector<T>, первый шаблон будет выбран для всего остального, а также в конце рекурсии.Приведенный выше пример вернет:

5
3

Демо: https://ideone.com/CLucGA

0 голосов
/ 07 июня 2018

Простой шаблон должен решить эту проблему.По памяти:

template <T> singleFunction(vector<T> &t) {
    return t.size();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...