일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- diamond inheritance
- new&delete
- member function pointer
- 더 지니어스 양면포커
- std::vector
- suffix return type
- this call
- std::endl
- c++ multi chatting room
- delete function
- virtual destructor
- C++
- constructor
- std::cout
- c++ basic practice
- pointer to member data
- dynamic_cast
- placement new
- std::ostream
- virtual function table
- virtual inheritance
- return by reference
- base from member
- vector size
- vector capacity
- operator overloading
- discord bot
- conversion constructor
- virtual function
- increment operator
- Today
- Total
I'm FanJae.
[C++ Intermediate] Max Implement 본문
1. Max Implement
#include <iostream>
#include <string>
template<class T>
const T& mymax(const T& obj1, const T& obj2)
{
return obj1 < obj2 ? obj2 : obj1;
}
int main()
{
std::string s1 = "abcd";
std::string s2 = "xyz";
auto ret1 = mymax(s1, s2);
auto ret2 = mymax(s1.size(), s2.size());
std::cout << ret1 << std::endl;
}
1-1. 알고리즘 함수가 사용하는 정책(비교방식)을 변경하는 방법.
① 알고리즘 함수가 사용하는 정책(비교방식)을 변경하고 싶을때 보통 이항 조건자를 사용한다. (C++ STL)
std::sort(v.begin(),v.end(), [](auto &a, auto&b) { return a.size() < b.size(); } );
#include <iostream>
#include <string>
template<class T>
const T& mymax(const T& obj1, const T& obj2)
{
return obj1 < obj2 ? obj2 : obj1;
}
int main()
{
std::string s1 = "abcd";
std::string s2 = "xyz";
auto ret1 = mymax(s1, s2);
auto ret2 = mymax(s1.size(), s2.size());
auto ret3 = mymax(s1, s2, [](auto& a, auto& b) { return a.size() > b.size(); } );
auto ret4 = mymax(s1, s2, [](auto& a) { return a.size(); } );
// f(s1) < f(s2)
std::cout << ret2 << std::endl;
}
② 단항 조건자를 사용하는 방법
sorted(str_list, key = lambda x : len(x) );
- Python이 사용하는 방식.
③ 방법 1과 방법 2를 모두 사용하는 방법
- C++20 Range Algorithm의 원리
- 멤버 함수 포인터, 멤버 데이터, std::invoke 활용.
#include <iostream>
#include <string>
template<class T, class Proj>
const T& mymax(const T& obj1, const T& obj2, Proj proj)
{
return proj(obj1) < proj(ob2) ? obj2 : obj1;
}
int main()
{
std::string s1 = "abcd";
std::string s2 = "xyz";
auto ret1 = mymax(s1, s2, [](auto &a) { return a.size() ; }
std::cout << ret1 << std::endl;
}
- mymax의 3번째 인자로 단항 조건자를 전달한다.
- 비교시 조건자의 결과를 놓고 비교한다.
proj(obj1) < proj(obj2)
- C++20에서 Projection이라고 칭해지는 개념이다.
※ 단항 조건자 대신 멤버 함수의 포인터를 보낼 수 없을까?
#include <iostream>
#include <string>
#include <functional>
template<class T, class Proj>
const T& mymax(const T& obj1, const T& obj2, Proj proj)
{
// return proj(obj1) < proj(ob2) ? obj2 : obj1;
return std::invoke(proj, obj1) < std::invoke(proj, obj2) ? obj2 : obj1;
}
int main()
{
std::string s1 = "abcd";
std::string s2 = "xyz";
auto ret1 = mymax(s1, s2, [](auto &a) { return a.size() ; }
auto ret2 = mymax(s1, s2, &std::string::size );
std::cout << ret1 << std::endl;
}
- std::invoke()를 사용하면 된다.
proj(obj1) | proj가 일반 함수라면 OK. 멤버 함수 라면 Error. |
std::invoke(proj,obj1) | Proj가 일반 함수 뿐 아니라 멤버 함수라도 Ok. |
- projection 인자는 생략할 수 있어야 한다.
- Proj 템플릿 인자의 디폴트 값이 필요하다.
1-2. std::identity ( C++ 20 )
#include <iostream>
#include <string>
#include <functional>
template<class T, class Proj = std::identity>
const T& mymax(const T& obj1, const T& obj2, Proj proj = { }) // Default 객체 사용.
{
return std::invoke(proj, obj1) < std::invoke(proj, obj2) ? obj2 : obj1;
// f(obj1)
}
int main()
{
std::string s1 = "abcd";
std::string s2 = "xyz";
std::identity f;
auto& r = f(s1); // 반환 값으로 내 자신의 참조가 나옴.
std::cout << &s1 << std::endl;
std::cout << &r << std::endl;
auto ret = mymax(s1, s2);
std::cout << ret << std::endl;
}
- 전달 받은 인자를 어떠한 변화도 없이 그대로 반환하는 함수 객체
- <functional>
- C++20 부터 지원되지만 C++11 문법으로도 구현가능하다. (단, [[nodiscard]] 는 C++17)
- std::identity 구현에 사용된 기술은 Perfect Forwarding과 Callable에서 다룸.
1-3. 멤버 변수 포인터도 적용된다.
#include <iostream>
#include <string>
#include <functional>
template<class T, class Proj = std::identity>
const T& mymax(const T& obj1, const T& obj2, Proj proj = { }) // Default 객체 사용.
{
return std::invoke(proj, obj1) < std::invoke(proj, obj2) ? obj2 : obj1;
// (obj1.*proj) < (obj2.*proj)
}
struct Point
{
int x, y;
};
int main()
{
Point p1 = {2, 0};
Point p2 = {1, 1};
auto ret = mymax(p1, p2, &Point::y ); // y값만 비교하라.
std::cout << ret.x << ", " << ret.y << std::endl;
}
- 멤버 함수 포인터 뿐 아니라 멤버 변수 포인터도 std::invoke를 사용할 수 있다.
projection 생략 | mymax(s1, s2); |
단항 조건자 | mymax(s1, s2, [](auto& a) { return a.size(); } ); |
멤버 함수 포인터 | mymax(s1, s2, &std::string::size); |
멤버 변수 포인터 | mymax(p1, p2, &Point::y); |
2. Max Implement 발전
- Callable 관련 내용을 듣고와서 다시 보려고 한다.
3.
포스트를 적다가 앞의 내용부터 다시 한번 보고 오는게 좋을듯 하여 재 복습을 해보려 한다.
'C++ > Intermediate' 카테고리의 다른 글
[C++ Intermediate] Member Function Pointer (2) | 2024.09.23 |
---|---|
[C++ Intermediate] this call (1) | 2024.09.22 |
[C++ Intermediate] Trivial (4) | 2024.09.19 |
[C++ Intermediate] new/delete, placement new (0) | 2024.09.18 |
[C++ Intermediate] 객체의 변환(Conversion) (0) | 2024.09.13 |