🧼C, C++/흑마법

배열의 차원을 구하는 방법 C++

Mawile 2021. 10. 11.
728x90

[ 강화버전 ]

https://mawile.tistory.com/207

 

배열의 차원을 구하는 방법 C++ (강화버전)

안녕하세요!! 이번에는 저번에 배열의 차원의 찻수를 구하는 방법에 관하여 포스팅했습니다. 몇시간 더 삽질하면서, "벡터에 클래스가 들어와도 정상적으로 작동시킬수 없을까?"라는 생각이 들

mawile.tistory.com

 


 

우리는 흔히 배열의 크기를 구하고는 합니다.

예를들어서 이런식으로 말이죠..

 

int main() {
	int arr[5];
    	int size = sizeof(arr) / sizeof(arr[0]);
}

 

하지만 ...

만약 아래 코드와 같은 5차원 배열이 존재할때, 이 배열의 찻수인 "5"를 프로그램에게 알리려면...

즉, n차원 배열이 있다고할때, 프로그램에게 그 n차원 배열에서의 찻수 n이 몇인지 알려면 어떻게 해야할까요..?

int main() {
	int arr[5][4][3][2][1];
    	int DimensionOfArr; // ???,  n은 5 !
}

 

 

 

배열의 차원의 찻수 구하기
#include <iostream>
#include <vector>
#include <type_traits>

// 벡터전용 찻수구하기 함수 (배열, 찻수) [실제로는 안쓰는 함수]
template<class dataType>
constexpr inline std::size_t getDimension_Vector(dataType& Vector, std::size_t size){
	auto CopiedVector{Vector};
	if constexpr(std::is_class<decltype(CopiedVector)>::value){
		if(CopiedVector.empty()) CopiedVector.push_back({});
		return getDimension_Vector(CopiedVector[0], ++size);
	}
	return --size;
}

// 벡터전용 찻수구하기 함수 (배열) [실제로 쓰이는 함수]
template<class dataType>
constexpr inline std::size_t getDimension_Vector(dataType& Vector){
	if constexpr(std::is_class<dataType>::value){
		auto CopiedVector{Vector};
		if(CopiedVector.empty()) CopiedVector.push_back({});
		return getDimension_Vector(CopiedVector, 1);
	}
	return 1;
}

// 일반배열용 찻수구하기 함수
template<class dataType>

// Array에 레퍼런스를 안씌우면 포인터로 인식하고 제대로 된 결과값을 얻을 수 없음.
constexpr inline std::size_t getDimension_Array(dataType& Array){
	return std::rank<dataType>::value;
}

int main() {
	std::vector<std::vector<std::vector<std::vector<int>>>> vec; // 차원 수: 4
	int arr[5][4][3][2][1]; // 차원 수: 5
	
	std::cout << getDimension_Vector(vec) << '\n'; // = 4
	std::cout << getDimension_Array(arr) << '\n'; // = 5
}

결과값

 

저는 그냥 갑자기 생각나서 즉석으로 감각적으로 짰지만..

완성해보니 함수 모양새가 좀 기묘합니다..

 

메커니즘은 매우매우~~ 간단합니다.

 

메커니즘

우선 밑에있는 "getDimension_Vector"함수는 파라미터로 들어온 인수를 클래스인지 감별합니다.

(이것때문에 std::vector의 데이터가 클래스면은 정상작동이 안됩니다...ㅠ{한계점})

만약 클래스가아니면은(일반 데이터면은) 1을 반환하고 아니면은 내용물이 빈 벡터인지 확인하고,

비어있으면 빈 데이터를 넣어준다음...(오버플로우 방지)

위쪽에 오버로딩된 "getDimension_Vector"함수를 호출합니다.

 

위쪽에 존재하는 "getDimension_Vector"함수는 위와 똑같은 과정을 거치고는 재귀적으로 같은 함수를 호출하는데,

아래쪽에 존재하는 "getDimension_Vector"함수와의 다른점이라고 한다면, 자신의 0번째 인덱스원소를 전달한다는 점입니다. 자신의 0번째원소를 전달함으로써, 현재 자신보다 한 단계 낮은 차원의 수의 요소를 전달 하게 되는거죠.

 

그리고 언젠가 자신의 차원의 수가 0이 된다면 현재 자신의 차원의 수를 저장하고있는 "size"에서 1을 뺀값을 최종적으로 반환합니다.. 어때요 간단하죠?

 

 

그리고 "getDimension_Array"는 그냥 std::rank 개량한 것이기 때문에 크게 설명안하겠습니다.

"std::rank"가 궁금하신 분들은 밑에 링크타고 들어가주시면됩니다~!!

https://en.cppreference.com/w/cpp/types/rank

 

std::rank - cppreference.com

template< class T > struct rank; (since C++11) If T is an array type, provides the member constant value equal to the number of dimensions of the array. For any other type, value is 0. The behavior of a program that adds specializations for rank or rank_v

en.cppreference.com

 

궁금한점이 있으신 분들은 댓글로 질문주세요!

그럼 안녕~~~!!


728x90

댓글