C++11에서 C++17의 std::filesystem 사용하기

Filesystem

std::filesystem은 진짜 좋습니다…

아쉬운 점은 std::filesystemC++17에서 채택되었다는 점입니다.

그러면 C++11/14쟁이들은 영원히 path에서 고통받아야하는건가요?

회사 업무로 인해 C++17에서 작업을 하다가 C++11로 내려와야했던 저는, 이 발암을 없애기 위해 가장 먼저 filesystem의 대체제를 찾았습니다.

Filesystem이 왜 좋은가?

C++ 코딩을 하다보면 다들 다르게 경로를 적는 방법이 다릅니다.

Windows에서는 경로를 \\로 가르고, UNIX 기반의 Linux와 MacOS는 경로를 /로 가릅니다.

사람마다도 경로를 다르게 적습니다. 누구는 절대경로를 좋아하고, 누구는 상대경로를 좋아합니다.

그래서인지 다른 컴퓨터에서 코드를 끌고와서 빌드하면 파일을 못찾고 다 터집니다 허허

이런 열받는 상황을 타파하는 솔루션은 std::filesystem입니다.

경로 관련 작업을 1. 안전하게, 2. 크로스플랫폼 지원하며, 3. 가독성 좋게 만들어줄 수 있습니다.

 


대안 1: Boost/fileystem

장점: 쓰기 쉽다. Boost의 다른 기능들도 함께 쓸 수 있다.
단점: 겁.나. 무겁다

가장 뻔한 대안으로는 Boost 프레임워크를 사용하는 것입니다. Boost에는 C++에 적용될 수 있는 많은 모던한 기능들이 다 들어있습니다.

Boost 빌드를 하면서 filesystem을 타겟으로 빌드를 하면 Boost의 코어와 몇가지 라이브러리들을 기반으로 filesystem 구현체가 설치됩니다.

장점이라면, boost::filesystemstd::filesystem거의 API가 동일하며, 왠만한 경우 C++17로 작성된 코드에서 std->boost로 바꾸면 잘 작동합니다.

단점이라면, Boost filesystem은 설치를 하면 Debug/Release가 각각 약 150MB 정도로 굉장히 무겁습니다. Path 기능을 아무리 잘 짜봐야 전체 알고리즘에 비해 얼마나 차지하겠습니까? 1%도 안되는 부분인데, OpenCV의 3배가 되는 심볼이 올라가게 되는거라면 용량이 정말 걱정되는 수준입니다. Boost가 무겁다는건 듣긴 했지만 이정도일줄은… ㅋㅋ

 


대안 2: std::experimental::filesystem

장점: 외부 라이브러리가 필요없다. API가 동일하다.
단점: 컴파일러 버전 바뀌면 언제 없어질 지 모른다. 임베디드 컴파일러에서 지원 안할수도 있다.

그 다음 대안으로는 std::experimental을 사용하는 것입이다.

std::experimental은 현재 STL에서 추후 C++ standard에 포함시키려고 하는 기능들을 테스트하기 위해 만든 기능들입니다. 대부분 std::experimental에 올라간 기능들은 거의 확정으로 추후 C++ standard에 올라가게 됩니다.

특이한 점은, C++17에 이미 filesystem이 올라가있는데도 최신 GCC 컴파일러에 std::experimental::filesystem이 올라가있습니다. 기존의 C++17 코드에서 std::filesystem -> std::experiemental::filesystem으로 변경하고 C++11로 스탠다드를 내렸는데, 잘 작동했습니다.

이 방식은 Boost를 사용하는 방식에 비해, 전혀 외부 라이브러리를 이용하지 않아도 된다는 큰 강점을 가집니다.

단점이라면, 컴파일러 버전이 높아지면서 언제 사라질지 모릅니다. 또, 임베디드 타겟의 컴파일러라면 로딩되는 심볼을 줄이기 위해 experimental과 같은 기능들은 로딩하지 않았을 수도 있습니다. 로딩되지 않았다면 이 기능은 사용하지 못할 겁니다.