-
[37] - GeneratorsGraphics 2021. 8. 10. 14:08
Fill부터 살펴봅니다. 설명대로 어떤 Container를 채워주는 기능을 합니다. std::vector에 대해서 이 작업을 수행할 수도 있습니다. 하지만 벡터의 경우엔 자체적으로 초기화가 가능하며 Fill을 구태여 호출할 필요가 없습니다. 이 함수를 사용할 경우라면 벡터의 크기를 바꾸고 다시 채워넣을 필요가 있을 때 정도일 것입니다. 혹은 기존의 컨테이너 중간에 값을 삽입하거나 하는 기능에 활용할 수도 있습니다.
그런데 std::fill은 일관적인 값으로만 컨테이너를 채워줄 수 있습니다. 그게 아니라면 std::copy를 사용하는 편이 나을 것입니다. 만약 어떤 컨테이너의 특정 구간을 상승하는 값으로 채워주고 싶다면 std::iota를 사용할 수 있습니다.
아래의 실험적 코드를 보면 흥미로운 점이 있는데 <numeric> 헤더에 있다는 점에도 불구하고 char형태의 변수의 상승에 대해서도 적용이 된다는 점입니다. 가령 ASCII에서 'a'가 decimal로 97인가 96인가 그러함에도 불구하고 컨테이너가 std::string이거나 char형태이면 알아서 인식을 합니다.
Fill과 더불어서 다양한 활용의 가능성이 있는 standard library function입니다.
std::generate
어쩌면 이것이 본론이라고 할 수 있습니다.
C++20 표준은 아직 다루고 싶지 않습니다. 다음이 이 함수에 대한 디테일입니다. 한 가지 기쁜 일은 이제 overload resolution이라든가 function object, function pointer등의 용어를 알기 때문에 문서의 독해가 빨라졌다는 사실입니다.
Generate는 Functor나 function을 줍니다. 그리하면 해당 Generate에 따라 값을 만들어 줍니다. 다음과 같이 사용할 수 있습니다.
총 10개의 무작위 수를 만들어서 컨테이너에 채워 넣었습니다. 혹은 이런 방법도 가능할 것입니다.
그러나 이대로 컴파일을 시도하면 에러가 납니다.
원인은 d가 parameter를 요구하기 때문입니다. 하지만 generate_n의 함수는 paramter가 필요하지 않습니다. 그래서 해줄 수 있는 것은 몇 가지가 있는데 그 중 하나가 Lambda expression을 통해서 parameter를 bind해주는 것입니다.
문득 그냥 d(rng)를 넘겨주면 안 되는 것인가 싶어서 해보면 안됩니다. 위에서 말했던 것처럼 generate parameter는 다른 parameter를 받지 않기 때문입니다. 하지만 위의 람다 식을 사용하면 추가적인 parameter없이 성공적으로 원하는 바를 이룰 수 있습니다.
또 다른 방법은 아까 말했던 것처럼 std::bind를 통해서 bind하는 방법입니다.
이번에는 std::iota에 대한 응용을 생각해봅니다. std::iota는 어떤 Range의 컨테이너에 대해서 그것이 어떤 데이터 타입이든 정의된 단위크기 1 만큼만 증가시켜주고 결과를 격납한 컨테이너를 만들었습니다. 이번에는 1이 아니라 그 이상 또는 그 이하를 증가시켜보도록 합니다. 물론 std::iota를 사용해서는 안됩니다. std::iota는 정의가 되어 있기를 반드시 1만 증가시키도록 되어 있기 때문입니다. generate_n의 마지막 parameter를 잘 조정하면 만들 수 있을 것이라는 생각이 듭니다.
val의 type이 정의되지 않아서 생긴 에러가 아닙니다 여기서 람다의 중요한 성질을 하나 배울 수 있었는데 전에 Lambda에 대해 깊게 공부하며 알았던 람다의 가장 기본적인 표현식은 [] () "mutable" "throw" -> 'return type' {}; 였습니다. 또, 람다는 Function Object, Function pointer의 장점만 취합한 결과라 했고 Function Pointer는 Scope내부에서 State를 갖을 수 있었습니다. 저 mutable이 바로 그 장점을 살릴 때 쓰입니다. 람다는 기본적인 설정으로는 State를 가질 수 없기 때문에 10번의 insertion을 수행하면서 val의 값을 갖고 싶다면 mutable을 사용해 주어야 합니다. 전의 계산 결과를 바탕으로 다음의 계산을 수행하고 싶기 때문에 State를 가질 필요가 있습니다.
올바른 결과를 얻을 수 있습니다. std::sample
또 유용한 함수가 하나 있습니다. std::sample이라는 함수입니다.
이 함수의 설명을 읽어보면 n개의 전체집합에서 r개의 중복을 포함한 elements를 뽑는 것이 아니고 중복이 없는 r개의 원소를 뽑아주는 기능을 수행합니다. permutation이나 combination은 알고리즘 문제를 풀며 지겹도록 만들었습니다. 아마 standard library에 있을 것입니다.
Combination은 명시되어 있지 않았습니다 'Graphics' 카테고리의 다른 글
[39] - Partition (0) 2021.08.10 [38] - Permuters (0) 2021.08.10 [36] - find, search, reverse iterators (0) 2021.08.10 [35] - count, all, none_of (0) 2021.08.09 [34] - Transform, For_each (0) 2021.08.09