Notice
Recent Posts
Recent Comments
Link
- 책_곽용재님 홈페이지
- 책_노란북 - 책 가격비교
- 책_김재우-SICP번역
- 플밍_쏘쓰포지
- 플밍_CodingHorror ?
- 플밍_상킴
- 플밍_김민장님
- GPGStudy
- 플밍_미친감자님
- 플밍_jz
- 플밍_샤방샤방님
- 플밍_글쓰는프로그래머2
- 플밍_키보드후킹
- 사람_재혁
- 사람_kernel0
- 사람_박PD
- 사람_경석형
- 사람_nemo
- 사람_kikiwaka
- 사람_Junios
- 사람_harry
- 사람_어떤 개발자의 금서목록..
- 사람_모기소리
- 사람_낙타한마리
- 사람_redkuma
- 사람_영원의끝
- 사람_민식형
- 도스박스 다음카페
- 플레이웨어즈 - 게임하드웨어벤치마크
- http://puwazaza.com/
- David harvey의 Reading Marx's c…
- 씨네21
- 한겨레_임경선의 이기적인 상담실
- 본격2차대전만화 - 굽시니스트
- 영화_정성일 글모음 페이지
- 영화_영화속이데올로기파악하기
- 음식_생선회
- 죽력고
- 사람_한밀
- 플밍_수까락
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- 단상
- 진중권
- 진삼국무쌍5
- 고등학교 사회공부
- 영화
- 유시민
- BSP
- 삼국지6
- 소비자고발
- 책
- modernc++
- 노무현
- 일리아스
- 김두식
- 고전강의
- Programming
- 정신분석
- 유머
- 강유원
- 정성일
- 태그가 아깝다
- 프로그래밍
- 게임
- stl
- 건강
- template
- c++
- 인문학
- 삼국지
- programming challenges
Archives
- Today
- Total
01-05 01:43
lancelot.com
Pointer to member data 본문
- Pointer to member data
#include<iostream>
struct Point
{
int x;
int y;
};
int main()
{
int num = 0;
int* p1 = #
int Point::* p2 = &Point::y;// 멤버 함수포인터처럼 객체에.* 연산자를 사용해서 접근하기 위함
*p1 = 10; // ok
// *p2 = 10; // error
Point pt;
pt.*p2 = 10; // pt.y=10
// *( (char*)&pt+p2 )=10;
std::cout << p2 << std::endl;
printf("%p\n", p2);
}
- 멤버 데이터를 가리키는 포인터(p)를 사용해서 "객체의 멤버 데이터에 접근하는 2가지 방법"
#include<iostream>
struct Point
{
int x;
int y;
};
int main()
{
int Point::* p = &Point::y;
Point obj;
obj.*p = 10; // obj.y=10
(&obj)->*p = 10;
std::invoke(p, obj) = 20; // obj.y=20
int n = std::invoke(p, obj);
std::cout << n << std::endl;
std::cout << obj.y << std::endl;
}
- callable type
- std::invoke() 를 사용할 수 있는 타입
- 함수, 함수포인터, 멤버 함수포인터, 멤버 데이터포인터, 람다 표현식이 만드는 타입, operator() 함수를 제공하는 타입 등.
- 알고리즘 함수가 사용하는 "정책(비교방식) 을 변경"하고 싶다.
#include<iostream>
template<typename T>
const T& mymax(const T& obj1, const T& obj2)
{
return obj1 < obj2 ? obj2 : obj1;
}
int main()
{
std::string s1 = "abcde";
std::string s2 = "xyz";
auto ret1 = mymax(s1, s1);
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 << ret1 << std::endl<<ret2 << std::endl;
}
- Projection 개념 추가
- myprojmax() 의 3번째 인자로 단항 조건 연상자 전달
- 비교시 조건자의 결과를 비교
- proj(obj1) < proj(obj2)
- C++20 에서 "projection" 이라고 부르는 개념
- 비교시 조건자의 결과를 비교
- 단한 조건자 대신 "멤버 함수의 포인터"를 보낼 수 없을까?
- std::invoke() 를 사용하면 된다.
- proj(obj1) : proj가 일반함수라면 ok. 멤버함수라면 error
- std::invoke(proj, obj1) : proj가 일반함수 든 멤버함수든 ok
- std::invoke() 를 사용하면 된다.
- myprojmax() 의 3번째 인자로 단항 조건 연상자 전달
#include<iostream>
template<typename T>
const T& mymax(const T& obj1, const T& obj2)
{
return obj1 < obj2 ? obj2 : obj1;
}
template<typename T, typename Proj>
const T& myprojmax(const T& obj1, const T& obj2, Proj proj)
{
// 멤버함수의 경우 (obj2.*proj)() 이렇게 해야하므로 다른식의 구현이 필요하다.
// 하지만 아래 invokemax() 처럼 invoke를 사용하면 함수 하나로 사용 가능
return proj(obj1) < proj(obj2) ? obj2 : obj1;
}
template<typename T, typename Proj>
const T& invokemax(const T& obj1, const T& obj2, Proj proj)
{
return std::invoke(proj,obj1) < std::invoke(proj,obj2) ? obj2 : obj1;
}
int main()
{
std::string s1 = "abcde";
std::string s2 = "xyz";
auto ret1 = mymax(s1, s1);
auto ret2 = mymax(s1.size(), s2.size());
auto ret3 = invokemax(s1, s2, [](auto& a) { return a.size(); });
auto ret4 = invokemax(s1, s2, &std::string::size );
std::cout << ret1 << std::endl << ret2 << std::endl
std::cout << ret3 << std::endl << ret4 << std::endl;
}
- Proj 는 생략 가능해야한다
- defualt 인자가 필요
#include<iostream>
template<typename T, typename Proj=std::identity>
const T& mymax(const T& obj1, const T& obj2, Proj proj = {})
{
return std::invoke(proj,obj1) < std::invoke(proj,obj2) ? obj2 : obj1;
}
int main()
{
std::string s1 = "abcde";
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;
}
- std::identity ( C++20 )
- 전달받은 인자를 어떠한 변화도 없이 그대로 반환하는 함수객체
- <functional>
- C++20 부터 지원되지만 C++11문법으로도 구현가능( 단, [[nodiscard]]는 C++17 )
- perfect forwarding 과 callable 테크닉 사용
struct identity
{
template<class _Ty>
[[nodiscard]] constexpr _Ty&& operator() (_Ty& arg) const noexcept
{
return std::forward<_Ty>(arg);
}
using is_transparent = int;
};
- mymax 함수 사용법
- 멤버 함수 포인터 뿐 아니라 "멤버 변수 포인터도 std::invoke를 사용할 수 있다"
- mymax를 사용하는 방법
- projection 생략 : mymax(s1,s1);
- 단항 조건자 : mymax(s1,s2, [](auto& a) { return a.size(); } );
- 멤버함수 포인터 : mymax(s1,s1, &std::string::size);
- 멤버변수 포인터 : mymax(s1,s2, &Point.y);
#include<iostream>
template<typename T, typename Proj=std::identity>
const T& mymax(const T& obj1, const T& obj2, Proj proj = {})
{
return std::invoke(proj,obj1) < std::invoke(proj,obj2) ? obj2 : obj1;
}
struct Point
{
int x, y;
};
int main()
{
std::string s1 = "abcde";
std::string s2 = "xyz";
// mymax를 사용하는 방법
auto ret1 = mymax(s1, s1); // 1. projection 생략
auto ret2 = mymax(s1, s2, [](auto& a) { return a.size(); });// 2. 단항 조건자
auto ret3 = mymax(s1, s2, &std::string::size); // 3. 멤버함수 포인터
Point p1 = { 0,0 };
Point p2 = { 1,2 };
// function 을 전달하지 않고, y값만 가지고 비교하고싶을때도 가능
auto ret4 = mymax(p1, p2, &Point::y); // 4. 멤버변수 포인터
std::cout << ret4.x <<","<<ret4.y << std::endl;
}
- 비교 함수(객체) 교체 가능하도록
- projection 뿐 아니라 "비교 정책 자체를 교체" 할 수 있도록 "이항조건자(binary predicator)"를 함수 인자화 한다.
#include<iostream>
// 비교정책 자체가 교체가능하도록
template<typename T, class Comp=std::less<void>, typename Proj=std::identity>
const T& mymax(const T& obj1, const T& obj2, Comp comp= {}, Proj proj = {})
{
return std::invoke(comp, std::invoke(proj,obj1), std::invoke(proj,obj2) ) ? obj2 : obj1;
}
int main()
{
std::string s1 = "abcd";
std::string s2 = "xyz";
auto ret1=mymax(s1,s1); // 객체만 전달
auto ret2=mymax(s1,s2, std::greater{}); // 비교 함수객체 전달
auto ret3=mymax(s1,s2, {}, &std::string::size); // project 만 전달
auto ret4=mymax(s1,s2, std::greater{}, &std::string::size);// 비교 함수객체, project 모두 전달
std::cout << ret1 << std::endl;
std::cout << ret2 << std::endl;
std::cout << ret3 << std::endl;
std::cout << ret4 << std::endl;
std::cout<<std::max(s1, s2);
}
- mymax 를 사용하는 방법
- 객체만 전달 : mymax(s1,s1)
- 비교 함수객체 전달 : mymax(s1,s2, std::greater{});
- project 만 전달 : mymax(s1,s2, {}, &std::string::size);
- 비교 함수객체, project 모두 전달 : mymax(s1,s2, std::greater{}, &std::string::size);
- 왜, 템플릿의 디폴트인자를 "std::less<T> 가 아닌 std::less<void>" 로 했을까?
- C++20에 도입된 Range Algorithm
- <Algorithm> header
- 알고리즘의 "비교 정책을 교체" 할 수 있다.
- "Projection을 전달" 할 수 있다
- 멤버함수 포인터와 멤버 데이터 포인터 모두 사용가능
- 반복자 구간이 아닌 컨테이너를 전달 받는다.
- std::range::max 는 함수 객체(템플릿) 이다.
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
int main()
{
std::string s1 = "abcd";
std::string s2 = "xyz";
auto ret1 = std::ranges::max(s1, s2, std::greater{}, &std::string::size);
std::cout << ret1 << std::endl;
std::vector<std::string> v = { "hello", "a", "xxx", "zz" };
std::ranges::sort(v, std::greater{}, &std::string::size);
for(auto& e : v)
std::cout << e << std::endl;
}