BLOG main image
분류 전체보기 (222)
Reversing (13)
Pwnable (4)
Linux Kernel (3)
Crypto (2)
Wargames (66)
Programming (18)
Write Up (32)
Project (22)
Web (2)
My Life (52)
Memo (3)
etc (2)
발표자료 (1)
36,063 Visitors up to today!
Today 12 hit, Yesterday 30 hit
daisy rss
tistory 티스토리 가입하기!
'Programming/C++'에 해당되는 글 3건
2018.04.24 21:22
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <iterator>
#include <string>
 
int main(void)
{
  std::istreambuf_iterator<char> begin(std::cin), end;
  std::string s(beginend);
  std::cout << s;
 
  return 0;
}
cs


'Programming > C++' 카테고리의 다른 글

C++에서 문자열 EOF까지 입력받고 출력하기  (0) 2018.04.24
c++ 템플릿 공부  (0) 2017.08.29
Lvalue와 Rvalue  (0) 2017.05.20
Name
Password
Homepage
Secret
2017.08.29 14:16


두 값을 더하는 add연산을 하는 함수를 만들어야 한다는 상황을 가정해보자

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
32
33
34
35
36
37
38
39
40
41
#include <iostream>
 
/*
int add(int a, int b) {
    return a + b;
}
double add(double a, double b) {
    return a + b;
}
std::string add(std::string a, std::string b) {
    return a + b;
}
*/
 
template <typename T>
T add(T a, T b) {
    return a + b;
}
 
// 특수화 (Specialization)
template <typename T>
int add(int* a, int* b) {
    return *+ *b;
}
 
int main(void) {
    int a = 10, b = 20;
    double c = 10.4, d = 20.4;
    std::string s = "Hello", t = "World";
    int* pA = &a;
    int* pB = &b;
 
    int sum = add(a, b);
    double sum2 = add(c, d);
    std::string sum3 = add(s, t);
    int pSum = add<int*>(pA, pB);    // using specialization template
 
    std::cout << pSum << std::endl;
}
cs

템플릿이 없었다면 주석처럼 각 타입마다 모두 add함수를 만들어서 사용해야 할 것이다.
그런데 템플릿을 사용하면 이렇게 타입에 대해서 T로 표시하고 어찌어찌 해서 들어오는 타입대로 더할 수 있게 된다.
특정 자료형만 따로 정의할 일이 있으면 위에처럼 특수화를 해서 정의하면 된다.

그럼 int와 double은 어떻게 더해야 하는가? 
int + double은 double이지만 어떤 값이 double인지 알아내기는 쉽지 않다.
여러가지 대처 방법이 있을 수 있는데 가장 무난하고 권장되는 방법은

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
template <typename T1, typename T2>
auto add(T1 a, T2 b) -> decltype(a + b) {
    return a + b;
}
 
int main(void) {
    auto e = 10.4f;
    decltype(e) f = 24.5f;    // e의 타입으로 정의
 
    int a = 10;
    double b = 20.4;
 
    std::cout << add(a, b) << std::endl;
    std::cout << add(b, a) << std::endl;
}
cs

이렇게 auto로 반환하되 auto의 타입을 decltype을 이용해서 a + b의 타입으로 맞춰주면 된다.

다음은 가변인자에 대한 가변 템플릿이다.

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
32
33
34
35
36
37
38
39
#include <iostream>
 
/*
int sum(int a, int b) {
    return a + b;
}
int sum(int a, int b, int c) {
    return a + b + c;
}
int sum(int a, int b, int c, int d) {
    return a + b + c + d;
}
int sum(int a, int b, int c, int d, int e) {
    return a + b + c + d + e;
}
// ...
*/
 
// C++11 : Variadic Template (가변 템플릿)
template <typename T, typename... Args>
T sum(T a, Args... args) {
    return a + sum(args...);
}
 
template <typename T>
T sum(T a) {
    return a;
}
 
int main(void) {
    int a = 1, b = 2, c = 3;
 
    std::cout << sum(a, b) << std::endl;
    std::cout << sum(a, b, c) << std::endl;
}
cs

가변 템플릿이 없었다면 주석에 있는 것처럼 모든 인자의 개수에 맞춰서 다 정의를 미리 해주어야한다.
그런데 가변 템플릿을 사용하면 그럴 필요가 없다.

가변 템플릿은 재귀적인 형태로 이루어지며 가변 인수를 받는 템플릿 함수와 재귀적으로 돌다가 인자가 하나만 남았을 때 처리하는 함수 총 두개가 필요하다.

가변 템플릿은 위에 처럼 쓰면 댄다.
그리고 저 가변 템플릿은 코드상에서는 재귀지만 컴파일 타임때 재귀는 모두 풀리고 그냥 함수로 풀려서 실제 컴파일 하면 재귀로 실행되지 않는다.
그래서 재귀함수의 오버헤드가 발생하지 않는다.

그럼 가변 템플릿과 이것 저것을 응용해서 

1
2
3
4
5
6
#include <iostream>
 
int main(void) {
    std::cout << 'a' << 3 << "String" << 3.14 << std::endl;
    PrintList('a'3"String"3.14);
}
cs

4번 라인과 5번 라인이 똑같이 나오도록 PrintList함수를 만들어보자.

물론 인자 개수와 타입은 각각 바뀔 수 있다.

알아서 만들자

'Programming > C++' 카테고리의 다른 글

C++에서 문자열 EOF까지 입력받고 출력하기  (0) 2018.04.24
c++ 템플릿 공부  (0) 2017.08.29
Lvalue와 Rvalue  (0) 2017.05.20
Name
Password
Homepage
Secret
2017.05.20 11:37


오늘 한거

1. Reference
2. C언어에서의 Lvalue와 Rvalue
3. C++에서의 Lvalue와 Rvalue
4. Rvalue Reference
5. 클래스를 생성할 때 기본으로 생성되는 것들 (6가지)

1. Reference

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;
 
void swap(int&a, int&b) {
    int tmp = a;
    a = b;
    b = tmp;
}
 
int main(void) {
    int a = 10, b = 20;
    int& rA = a;
 
    cout << a << endl;
    cout << rA << endl;
    cout << &<< endl;
    cout << &rA << endl;
 
    swap(a, b);
 
    cout << "a : " << a << ", b : " << b << endl;
 
    return 0;
}
cs

이렇당. rA는 a와 같은 값을 가지고 있다. 그리고 주소를 출력해 보면 a와 rA의 주소가 같다. 닉네임 같은거다. 그래서 swap할 때 많이 쓰인당


2. C언어에서의 Lvalue와 Rvalue

C언어에서의 Lvalue와 Rvalue를 보자. int a = 10; 변수에 값을 대입하는 코드이다.
Lvalue는 위 구문에서 왼쪽과 오른쪽 모두 올 수 있는 값이다. 그리고 Rvalue는 오른쪽에만 올 수 있는 값이다. 10 = a; 이런거는 안된당ㅎㅎ 대체적으로 Lvalue는 변수, Rvalue는 상수를 의미한다.


3. C++에서의 Lvalue와 Rvalue

C++에서는 Lvalue Rvalue 구분을 해당 구문이 지난 후에 그 값이 남아있는가로 구분한다. 

'Programming > C++' 카테고리의 다른 글

C++에서 문자열 EOF까지 입력받고 출력하기  (0) 2018.04.24
c++ 템플릿 공부  (0) 2017.08.29
Lvalue와 Rvalue  (0) 2017.05.20
Name
Password
Homepage
Secret
prev"" #1 next