2024. 8. 4. 22:05ㆍ프로그래밍 (확장)/More C++ Idioms
C++에서 함수 오버로딩과 템플릿을 활용하여 조건에 따라 다른 함수 호출을 선택하는 기법으로 조건에 따른 코드를 간결하고 효율적으로 작성할 수 있다.
https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Tag_Dispatching
More C++ Idioms/Tag Dispatching - Wikibooks, open books for an open world
From Wikibooks, open books for an open world Jump to navigation Jump to search Simplify writing multiple SFINAE-constrained overloads. Tag dispatching is a useful complement to enable_if. It can also be used in conjunction with trailing return type and dec
en.wikibooks.org
More C++ Idioms의 예시를 보면
namespace detail
{
// empty class (https://gangdonggil.tistory.com/65)
struct pick_3{};
struct pick_2 : public pick_3{};
struct pick_1 : public pick_2{};
constexpr pick_1 selector{};
}
우선순위가 pick_1 > pick_2 > pick_3이 되도록 상속구조가 잡혀 있다.
selector는 기본적으로 pick_1을 사용하도록 되어 있으므로 pick_1을 먼저 확인 할 것이다.
각 함수 템플릿의 구현부를 보면
auto function() -> decltype() 에서 함수 템플릿의 반환 타입을 조건부로 결정하게 되는데, 이 조건이 만족되어야 함수가 정의된다. (이 부분은 별도로 다루게 되면 링크 추가 예정)
우선순위가 가장 높은 pick_1을 인자로 구현된 첫번째 remove_if를 살펴보면,
template <typename Cont, typename Op>
auto remove_if(pick_1, Cont& cont, Op&& op)
-> decltype(cont.remove_if(std::forward<Op>(op)), void())
{
cont.remove_if(std::forward<Op>(op));
}
(decltype & SFINAE) 컴파일 타임에 cont.remove_if가 유효한지 검사. 유효하면 이 함수를 우선 호출하게 됨.
template <typename Cont, typename Op>
auto remove_if(pick_2, Cont& cont, Op&& op)
-> decltype(cont.erase(std::remove_if(std::begin(cont), std::end(cont), std::forward<Op>(op)), std::end(cont)), void())
{
cont.erase(std::remove_if(std::begin(cont), std::end(cont), std::forward<Op>(op)), std::end(cont));
}
(decltype & SFINAE) cont.erase(std::remove_if(std::begin(cont), std::end(cont)가 유효한지 검사. 가능한 경우 이 함수 호출.
template <typename Cont, typename Op>
void remove_if(pick_3, Cont& cont, Op&& op)
{
auto it = std::begin(cont);
auto end = std::end(cont);
while (it != end)
{
if (std::invoke_r<bool>(std::forward<Op>(op), *it))
it = cont.erase(it);
else
++it;
}
}
수동으로 반복해서 조건에 해당하는 요소를 제거하는 함수로 앞의 두 함수가 모두 실패하면 호출된다.
호출하는 코드의 예시를 만들어 본다면,
std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
remove_if(vec, [](int n) { return n % 2 == 0; }); // 짝수 제거
이 경우 vector는 remove_if 맴버 함수가 없으므로 첫 번째 함수는 제외되고, erase와 std::remove_if를 사용할 수 있으므로 pick_2 함수를 선택해서 사용하게 된다.
연관 글:
https://gangdonggil.tistory.com/65
std::is_empty (C++11~)
출처: https://en.cppreference.com/w/cpp/types/is_empty struct is_empty; (since C++11) std::is_empty is a UnaryTypeTrait. If T is an empty type (that is, a non-union class type with no non-static data members other than bit-fields of size 0, no virtual f
gangdonggil.tistory.com
https://gangdonggil.tistory.com/73
auto -> decltype(표현식)
함수 반환 타입을 지정할 때 사용하는 구문으로 함수의 반환 타입을 컴파일러가 자동으로 추론하고, 그 타입을 decltype을 사용하여 명시적으로 지정한다. 특히 함수 템플릿에서 유용하고, 주로
gangdonggil.tistory.com
https://gangdonggil.tistory.com/77
SFINAE (Substitution Failure Is Not An Error)
출처: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/SFINAE More C++ Idioms/SFINAE - Wikibooks, open books for an open worldFrom Wikibooks, open books for an open world Jump to navigation Jump to search Prune functions that do not yield valid templat
gangdonggil.tistory.com
'프로그래밍 (확장) > More C++ Idioms' 카테고리의 다른 글
More C++ Idioms (79. SFINAE - Substitution Failure Is Not An Error) (0) | 2024.08.28 |
---|---|
More C++ Idioms (55. Named Parameter) (0) | 2024.08.11 |
More C++ Idioms (44. Int-To-Type, Int2Type) (0) | 2024.08.05 |
More C++ Idioms Site (0) | 2024.08.04 |