뭔가 너무 과도하게 많은 선을 사용해서 오히려 특징이 안 사는 듯.
강사는 얇게 깎은 연필로 디테일을 강조하라고 했는데 따로 준비해야 할듯.
아직도 명암 연결부위가 자연스럽지 않음.
결국 사과같지 않음 ㅠㅠ
오히려 배에 가깝나....
뭔가 너무 과도하게 많은 선을 사용해서 오히려 특징이 안 사는 듯.
강사는 얇게 깎은 연필로 디테일을 강조하라고 했는데 따로 준비해야 할듯.
아직도 명암 연결부위가 자연스럽지 않음.
결국 사과같지 않음 ㅠㅠ
오히려 배에 가깝나....
개발자라면 자신이 사용하고 있는 도구들에 대한 개념을 어느 정도는 이해하고 있어야만 합니다. 그런 의미에서 ADB( Android Debug Bridge )에 대한 글을 번역해 보았습니다.
원문 : Android Debug Bridge.
주의 : 번역이 개판이므로 이상하면 반드시 원문을 참조하세요.
주의 : 가독성을 높이기 위해서 발음이 비슷하거나 잘 알려진 용어는 한글로 표기합니다.
주의 : 허락받고 번역한 것이 아니므로 언제든 내려갈 수 있습니다.
Android Debug Bridge
Android Debug Bridge( adb )는 다용도의 명령줄 도구인데, 당신이 에뮬레이터 인스턴스나 안드로이드용 장치와 통신할 수 있도록 해 준다. 이는 클라이언트-서버 프로그램으로, 세 가지 요소를 포함한다.
당신은 adb 도구를 <sdk>/paltform-tools/ 에서 찾을 수 있다.
당신이 adb 클라이언트를 실행할 때, 그 클라이언트는 먼저 이미 실행중인 adb 서버 프로세스가 존재하는지를 검사한다. 만약 존재하지 않으면, 그것은 서버 프로세스를 실행한다. 서버가 시작될 때, 그것은 로컬 TCP 포트 5037 에 연결되며, adb 클라이언트들로부터 보내지는 명령들을 받는다 - 모든 adb 클라이언트들은 5037 포트를 사용해서 adb 서버와 통신한다.
그리고 나서 서버는 모든 실행중인 에뮬레이터/장치 인스턴스들에 대한 연결을 설정한다. 그것은 에뮬레이터/장치들에 의해 사용되는 5555 에서 5585 사이의 홀수 번호 포트들을 스캐닝함으로써 에뮬레이터/장치 인스턴스들을 배치한다. 서버가 adb daemon 을 찾으면, 그것은 그 포트에 연결을 설정한다. 각 에뮬레이터/장치 인스턴스들은 연속된 포트의 쌍을 요청한다는데 주의하라 - 콘솔 연결을 위해 짝수 번호 포트를 사용하고, adb 연결을 위해 홀수 번호 포트를 사용한다. 예를 들어 :
에뮬레이터 1, 콘솔 : 5554
에뮬레이터 1, adb : 5555
에뮬레이터 2, 콘솔 : 5556
에뮬레이터 2, adb : 5557
이런 식이다...
위에서 보이듯이 5555 포트에 연결된 에뮬레이터 인스턴스는 5554 포트에서 응답을 받는 콘솔의 인스턴스와 동일하다.
일단 서버가 모든 에뮬레이터 인스턴스들에 대한 연결을 설정하고 나면, 당신은 adb 명령을 사용해서 그러한 인스턴스들에 접근할 수 있다. 서버는 에뮬레이터/장치 인스턴스들에 대한 연결을 관리하고 다중의 adb 클라이언트들로부터의 명령을 다루기 때문에, 당신은 모든 클라이언트들( 혹은 스크립트 )로부터 모든 메율레이터/장치 인스턴스들을 제어할 수 있다.
Syntax
당신은 개발 머신의 명령줄이나 스크립트에서 adb 명령을 제출issue할 수 있다. 용례는 다음과 같다 :
만약 단 하나의 에뮬레이터가 실행되고 있거나 단 하나의 장치만이 연결되어 있다면, adb 명령은 기본적으로 그 장치로 보내 진다. 만약 다중의 에뮬레이터가 실행되고 있거나 다중의 장치가 연결되어 있다면, 당신은 -d, -e, -s 옵션을 사용해서 그 명령이 향해야만 하는 대상 장치를 지정해야할 필요가 있다.
Commands
아래 표는 지원되는 adb 명령들을 모두 열거하고, 그것들의 의미 및 용례를 설명한다.
표1. 이용 가능한 adb 명령들.
Category | Command | Description | Comments |
Target Device |
-d | adb 명령이 연결된 하나의 USB 장치로만 향함. |
두 개 이상의 USB 장치가 연결되어 있다면 에러를 반환함. |
-e | adb 명령이 실행중인 단 하나의 에뮬레이터 인스턴스로만 향함. |
두 개 이상의 에뮬레이터 인스턴스가 실행중이면 에러를 반환함. |
|
-s <serialNumber> | adb 명령이 특정 에뮬레이터/장치 인스턴스로 향함. adb 에 할당된 ( "emulator-5556" 과 같은 ) 시리얼 넘버에 의해서 지정됨. |
Directing Commands to a Specific Emulator/Device instance 를 참조하라. |
|
General | devices | 연결된 모든 에뮬레이터/장치 인스턴스들의 리스트를 출력함. |
더 많은 정보를 원한다면 Querying for Emulator/Devices Instances 를 참조하라. |
help | 지원되는 adb 명령들의 리스트를 출력함. | ||
version | adb 버전 번호를 출력함. | ||
Debug | logcat [option] [filter-specs] |
화면에 로그 데이터를 출력함. |
|
bugreport |
버그 리포팅을 위한 목적으로 dumpsys, dumpstate, logcat 데이터를 화면에 출력함. |
||
jdwp | 주어진 장치에서 이용 가능한 JDWP 프로세스들의 리스트를 출력함. |
당신은 forward jdwp:<pid> 포트 포워딩 명세를 사용해서 지정한 JDWP 프로세스에 연결할 수 있다. 예를 들어 : adb foward tcp:8000 jdwp:472 jdb -attach localhost:8000 |
|
Data | install <path-to-apk> |
안드로이트 응용프로그램을 에뮬레이터/장치에 밀어 넣음( .apk 파일의 전체 경로를 지정 ). |
|
pull <remote> <local> | 지정된 파일을 에뮬레이터/장치 인스턴스로부터 당신의 개발 컴퓨터로 복사함. |
||
push <local> <remote> |
지정되 파일을 당신의 개발 컴퓨터로부터 에뮬레이터/장치 인스턴스로 복사함. | ||
Port and Networking |
forward <local> <remote> |
소켓 연결들을 지정된 로컬 포트로부터 에뮬레이터/장치 인스턴스의 지정된 리모트 포트로 포워딩. | 포트 명세는 다음과 같은 정책을 사용할 수 있음 : local:<UNIX domain socket name> dev:<character device name> jdwp:<pid> |
ppp <tty> [param]... | USB 에 PPP 를 실행함.
당신은 자동적으로 PPP 연결을 시작해서는 안된다는 것에 주의하라. |
||
Scripting | get-serialno | adb 인스턴스 시리얼 넘버 문자열을 출력. |
더 많은 정보를 원한다면 Querying for Emulator/Device Instances 를 참조하라. |
get-state | 에뮬레이터/장치 인스턴스의 adb 상태를 출력. |
||
wait-for-device |
장치가 연결될 때까지 실행을 중지 - 즉 인스턴스 상태가 device 일 때까지. |
당신은 이 명령을 어떤 adb 명령들 앞에 배치할 수 있다. 그 명령들은 다른 명령들이 제출되기 전에 에뮬레이터/장치 인스턴스가 연결될 때까지 기다려야 하는 명령들이다. 아래 예가 있다. 이 명령은 전체 시스템이 완전히 부팅되기 전까지 adb 를 기다리게 하지는 않는다. 그러한 이유로, 당신은 그것을 완전히 시스템이 부팅되기를 요구하는 명령들 앞에다가 배치하면 안 된다. 그러한 예로, install 은 안드로이드 패키지 매니저를 요구하는데, 이는 시스템이 완전히 부팅된 후에만 이용 가능하다. 다음과 같은 명령은 에뮬레이터나 장치 인스턴스가 adb 서버에 연결되자 마자 install 명령을 제출하지만, 안드로이드 시스템은 완전히 부팅되어 있기 전이다. 그래서 그것은 에러를 만들 것이다. |
|
Server | start-server | adb 서버 프로세스가 실행중인지 검사하고, 실행중이 아니면 시작함. |
|
kill-server | adb 서버 프로세스를 종료함. |
||
Shell | shell | 리모트 쉘을 대상 에뮬레이터/장치 인스턴스에서 시작함. |
더 많은 정보를 원하면 Issuing Shell Commands 를 참조하라. |
shell [shellCommand] |
쉘 명령을 대상 에뮬레이터/장치 인스턴스에 제출하고, 리모드 쉘을 나감. |
Querying for Emulator/Device Instances
adb 명령을 제출하기 전에, 어떤 에뮬레이터/장치 인스턴스들이 adb 서버에 연결되는지 아는 것이 도움이 된다. 당신은 연결된 에뮬레이터/장치들의 리스트를 devices 명령을 사용해서 생성할 수 있다.
응답으로, adb 는 각 인스턴스에 대한 상태 정보를 출력한다.
각 인스턴스를 위한 출력은 다음과 같은 형식이다 :
여기 devices 명령과 그것의 출력을 보여 주는 예가 있다.
Directing Commands to a Specific Emulator/Device Instance
만약 다중의 에뮬레이터/장치 인스턴스들이 실행중이라면, 당신은 반드시 adb 명령들을 제출할 때 대상 인스턴스를 지정해야만 한다. 이를 위해서, 명령들에서 -s 옵션을 사용하라. -s 옵션의 용례는 다음과 같다.
보면 알겠지만, 당신은 adb 할당 시리얼 넘버를 사용해 명령을 위한 대상 인스턴스를 지정한다. 당신은 devices 명령을 사용해 실행중인 에뮬레이터/장치 인스턴스들의 시리얼 넘버를 획득할 수 있다. 예를 들어 :
다중 장치들이 이용가능 할 때, 만약 당신이에뮬레이터/장치 인스턴스를 지정하지 않고 명령을 제출한다면, adb 는 에러를 생성한다는 것에 주의하라.
당신이 이용 가능한 다중의 장치( 하드웨어 혹은 에뮬레이터 )를 가지고 있지만 단 하나만이 에뮬레이터라면, 단순히 -e 옵션을 사용해 에뮬레이터에다가 명령들을 보내라. 이와 유사하게 다중의 장치들이 있지만 단 하나의 하드웨어 장치만이 연결되었다면, -d 옵션을 사용해서 하드웨어 장치에 명령을 보내라.
Installing an Application
당신은 개발 컴퓨터로부터의 응용프로그램을 복사해 에뮬레이터/장치 인스턴스에 설치하기 위해서 adb 를 사용할 수 있다. 이를 위해, install 명령을 사용하라. 그 명령을 사용하면, 당신은 설치하기 원하는 .apk 파일의 경로를 지정해야만 한다.
에뮬레이터/장치 인스턴스 상에 설치하고자 하는 .apk 을 생성하는 방법에 대한 더 많은 정보를 원한다면, Building and Running 을 참조하라.
만약 당신이 Eclipse IDE 를 사용하고 있고 ADT 플러그인이 설치되어 있다면, 당신은 에뮬레이터/장치 상에 응용프로그램을 설치하기 위해 adb( 혹은 aapt )를 직접 사용할 필요가 없다는 것을 기억하라. 대신에 ADT 플러그인이 당신을 위해 응용프로그램의 패키징과 설치를 처리해 준다.
Forwarding Ports
당신은 forward 명령을 사용해서 임의의 포트 포워딩을 설정할 수 있다 - 특정 호스트 포트상에서 에뮬레이터/장치 상의 다른 포트로의 포워딩 요청. 여기 6100 호스트 포트에서 에뮬레이터/장치 포트 7100 으로의 포워딩을 설정하는 방법이 다음에 나와 있다.
당신은 다음과 같이 이름있는 추상 UNIX 도메인 소켓들로 포워딩을 설정하기 위해서 adb 를 사용할 수 있다.
Copying Files to or from an Emulator/Device instance
당신은 adb 의 pull 과 push 명령들을 사용해서 에뮬레이터/장치 인스턴스로부터 혹은 인스턴스로 파일을 복사할 수 있다. 특정 위치로 APK 파일을 복사만하는 install 명령과는 다르게, pull 과 push 명령은 에뮬레이터/장치 인스턴스의 모든 위치로 임의의 디렉토리나 파일들을 복사할 수 있게 해 준다.
에뮬레이터나 장치로부터 파일이나 디렉토리( 그리고 그것의 하위 디렉토리들 )를 복사하기 위해서는, 다음과 같은 명령을 사용한다.
파일이나 디렉토리( 그리고 그것의 하위 디렉토리들 )를 에뮬레이터나 장치로 복사하기 위해서는, 다음과 같은 명령을 사용한다.
명령에서 <local> 과 <remote> 는 당신의 개발 머신( local ) 과 에뮬레이터/장치 인스턴스( remote ) 상의 대상 파일/디렉토리에 대한 경로를 가리킨다. 예를 들어 :
Using activity manager( am )
adb 쉘에서, 당신은 activity manager( am ) 도구를 사용해 명령들을 제출하여 activity 를 시작하고, 프로세스를 강제로 종료시키고, intent 를 송출하고broardcast, 장치 스크린 속성들을 수정하는 등과 같은 다양한 시스템 동작들을 수행할 수 있다. 쉘에 있는 동안, 그 문맥은 다음과 같다 :
당신은 remote 쉘에 진입하지 않고도 adb 로부터 직접적으로 activity manager 명령을 제출할 수도 있다. 예를 들어 :
표2. 이용 가능한 activity manager 명령들.
Command | Description |
start [options] <INTENT> |
<INTENT> 에 의해 지정된 Activity 를 시작한다. Specification for <INTENT> arguments 를 참조하라. Option 들은 다음과 같다:
|
startservice [options] <INTENT> | <INTENT> 에 의해 지정된 Service 를 시작한다. Specification for <INTENT> arguments 를 참조하라. 옵션들은 다음과 같다 :
|
force-stop <PACKAGE> |
<PACKAGE>와 연관된 모든 것들을 강제로 종료한다( 앱의 패키지 이름 ). |
kill [options] <PACKAGE> | <PACKAGE>와 연관된 모든 프로세스들을 종료한다. 이 명령은 종료하기 안전하고 다른 사용자 경험에 영향을 주지 않는 프로세스들만 죽인다. 옵션들은 다음과 같다 :
|
kill-all |
모든 백그라운드 프로세스들을 죽인다. |
broadcast [options] <INTENT> |
broadcast intent 를 제출한다. Specification for <INTENT> arguments 를 참조하라. 옵션들은 다음과 같다 : [--user <USER_ID>|all|current] : 어떤 사용자에게 보낼 것인지 지정한다; 만약 지정되지 않으면 모든 사용자에게 보낸다. |
instrument [options] <COMPONENT> |
Instrumentation 인스턴스를 사용해 모니터링을 시작한다. 일반적으로 대상 <COMPONENT> 는 <TEST_PACKAGE>/<RUNNER_CLASS> 형식이다. 옵션은 다음과 같다 :
|
profile start <PROCESS> <FILE> |
<PROCESS> 상에서 프로파일러를 시작하는데, 그 결과를 <FILE>에 쓴다. |
profile stop <PROCESS> |
<PROCESS> 상의 프로파일러를 중지시킨다. |
dumpheap [options] <PROCESS> <FILE> | <PROCESS> 의 힙을 덤프하는데, <FILE> 에 쓴다. 옵션들은 다음과 같다 :
|
set-debug-app [options] <PACKAGE> | 응용프로그램 <PACKAGE> 를 디버깅하기 위해 설정한다 : 옵션들은 다음과 같다 :
|
clear-debug-app | set-debug-app 를 사용해 디버깅중인 이전의 패키지를 클리어한다. |
monitor [options] | crash 나 ANR 을 모니터링하기 시작한다. 옵션들은 다음과 같다 :
|
screen-compat [on|off ] <PACKAGE> |
<PACKAGE> 의 screen compativility 를 제어한다. |
display-size [reset|<WxH>] |
에뮬레이터/장치 디스플레이 사이즈를 덮어 쓴다. 이 명령은 당신의 앱을 다양한 스크린 사이즈를 넘나들며 테스트하는데 유용하다. 이는 큰 스크린을 가진 장치를 사용해 작은 스크린 해상도를 미믹함으로써 이루어 진다. 예를 들어 : am display-size 1280x800 |
display-density <dpi> |
에뮬레이터/장치 디스플레이 밀도를 덮어 쓴다.이 명령은 높은 밀도의 스크린 환경 상에서 낮은 밀도의 스크린을 사용해 다양한 스크린 밀도를 넘나들며 당신의 앱을 테스트하는데 유용하다. 예를 들어 : am display-density 480 |
to-uri <INTENT> | 주어진 intent 명세를 URI 로서 출력한다. Specification for <INTENT> arguments 를 참조하라. |
to-intent-uri <INTENT> |
주어진 intent 명세를 intent 로서 출력한다 : URI. Specification for <INTENT> arguments 를 참조하라. |
Specification for <INTENT> arguments
<INTENT> 인자를 취하는 activity manager 명령들을 위해, 당신은 다음과 같은 옵션들을 사용해 intent 를 지정할 수 있다 :
-a <ACTION>
"android.intent.action.VIEW" 와 같은 intent action 을 지정한다. 당신은 이를 한 번만 선언할 수 있다.
-d <DATA_URI>
"content://contacts/people/1" 와 같은 intent data URI 를 지정한다. 당신은 이를 한 번만 선언할 수 있다.
-t <MIME_TYPE>
"image/png" 과 같은 intent MIME 타입을 추가한다. 당신은 이를 한 번만 선언할 수 있다.
-c <CATEGORY>
"android.intent.category.APP_CONTACTS" 와 같은 intent 카테고리를 지정한다.
-n <COMPONENT>
"com.example.app/.ExampleActivity" 와 같은 명시적인 intent 를 생성하기 위한 패키지 이름 접두어를 사용해 컴포넌트 이름을 지정한다..
-f <FLAGS>
intent 에 setFlags() 에 의해 지원되는 플래그를 추가한다.
--esn <EXTRA_KEY>
null extra 를 추가한다. 이 옵션은 URI intent 들에 대해서는 지원되지 않는다.
-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE>
문자 데이터를 key-value 쌍으로서 추가한다.
--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE>
Boolean 데이터를 key-value 쌍으로서 추가한다.
--ei <EXTRA_KEY> <EXTRA_INT_VALUE>
정수 데이터를 key-value 쌍으로서 추가한다.
--el <EXTRA_KEY> <EXTRA_LONG_VALUE>
Long 데이터를 key-value 쌍으로서 추가한다.
--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE>
실수 데이터를 key-value 쌍으로서 추가한다.
--eu <EXTRA_KEY> <EXTRA_URI_VALUE>
URI 데이터를 key-value 쌍으로서 추가한다.
--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>
ComponentName 개체로서 변환되고 전달될 컴포넌트의 이름을 추가한다.
--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]
정수 배열을 추가한다.
--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]
Long 배열을 추가한다.
--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]
실수 배열을 추가한다.
--grant-read-uri-permission
FLAG_GRANT_READ_URI_PERMISSION 플래그를 포함시킨다.
--grant-write-uri-permission
FLAG_GRANT_WRITE_URI_PERMISSION 플래그를 포함시킨다.
--debug-log-resolution
FLAG_DEBUG_LOG_RESOLUTION 플래그를 포함시킨다.
--exclude-stopped-packages
FLAG_EXCLUDE_STOPPED_PACKAGES 플래그를 포함시킨다.
--include-stopped-packages
FLAG_INCLUDE_STOPPED_PACKAGES 플래그를 포함시킨다.
--activity-brought-to-front
FLAG_ACTIVITY_BROUGHT_TO_FRONT 플래그를 포함시킨다.
--activity-clear-top
FLAG_ACTIVITY_CLEAR_TOP 플래그를 포함시킨다.
--activity-clear-when-task-reset
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET 플래그를 포함시킨다.
--activity-exclude-from-recents
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 플래그를 포함시킨다.
--activity-launched-from-history
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY 플래그를 포함시킨다.
--activity-multiple-task
FLAG_ACTIVITY_MULTIPLE_TASK 플래그를 포함시킨다.
--activity-no-animation
FLAG_ACTIVITY_NO_ANIMATION 플래그를 포함시킨다.
--activity-no-history
FLAG_ACTIVITY_NO_HISTORY 플래그를 포함시킨다
--activity-no-user-action
FLAG_ACTIVITY_NO_USER_ACTION 플래그를 포함시킨다.
--activity-previous-is-top
FLAG_ACTIVITY_PREVIOUS_IS_TOP 플래그를 포함시킨다.
--activity-reorder-to-front
FLAG_ACTIVITY_REORDER_TO_FRONT 플래그를 포함시킨다.
--activity-reset-task-if-needed
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 플래그를 포함시킨다.
--activity-single-top
FLAG_ACTIVITY_SINGLE_TOP 플래그를 포함시킨다.
--activity-clear-task
FLAG_ACTIVITY_CLEAR_TASK 플래그를 포함시킨다.
--activity-task-on-home
FLAG_ACTIVITY_TASK_ON_HOME 플래그를 포함시킨다.
--receiver-registered-only
FLAG_RECEIVER_REGISTERED_ONLY 플래그를 포함시킨다.
--receiver-replace-pending
FLAG_RECEIVER_REPLACE_PENDING 플래그를 포함시킨다.
--selector
intent 데이터와 타입을 설정하기 위해서 -d 와 -t 옵션의 사용을 요구한다.
<URI> <COMPONENT> <PACKAGE>
위의 옵션들 중 하나에 의해 한정되지 않을 때, 당신은 직접적으로 URI, 패키지 이름, 컴포넌트 이름을 지정할 수 있다. 인자가 한정되지 않았을 때, 그 도구는 그것이 ":"( 콜론 )을 포함한다면 그 인자를 URI 로 가정한다; 그것이 "/"( 슬래쉬 )를 포함하면 인자를 컴포넌트 이름으로 가정한다; 그렇지 않으면 그것은 인자를 패키지 이름으로 가정한다.
Using package manager( pm )
adb 쉘 안에서, 당신은 package manager( pm ) 도구를 사용하는 명령들을 제출함으로써 장치에 설치된 응용프로그램 패키지들 상에서의 동작과 질의를 수행할 수 있다. 쉘에 있는 동안, 그 문맥은 다음과 같다 :
당신은 remote 쉘에 진입하지 않고도 adb 로부터 package manager 명령을 직접적으로 제출할 수 있다. 예를 들어 :
표3. 이용 가능한 package manager 명령들.
Command | Description |
list packages [options] <FILTER> |
모든 패키지들을 출력하는데, 선택적으로 <FILTER> 에 있는 텍스트를 포함하는 패키지 이름을 가진 것들만 출력한다. 옵션 :
|
list permission-groups |
모든 알려진 권한 그룹들을 출력한다. |
list permissions [options] <GROUP> |
모든 알려진 권한 그룹들을 출력하는데, 선택적으로 <GROUP> 에 있는 것들만 출력한다. 옵션 :
|
list instrumentation | 모든 테스트 패키지를 열거함. 옵션 :
|
list features |
시스템의 모든 기능을 출력함. |
list libraries | 현재 장치에 의해 지원되는 모든 라이브러리들을 출력함. |
list users | 시스템상의 모든 사용자들을 출력함. |
path <PACKAGE> | 주어진 <PACKAGE>의 APK 경로를 출력함. |
install [options] <PATH> | 시스템에 ( <PATH>로 지정된 ) 패키지를 설치함. 옵션 :
|
uninstall [options] <PACKAGE> | 시스템에서 패키지를 제거. 옵션 :
|
clear <PACKAGE> | 패키지와 관련된 모든 데이터를 제거함. |
enable <PACKAGE_OR_COMPONENT> |
주어진 패키지나 컴포넌트를 이용 가능하게 함( "package/class" 로 작성됨). |
disable <PACKAGE_OR_COMPONENT> |
주어진 패키지나 컴포넌트를 이용 불가능하게 함( "package/class" 로 작성됨). |
disable-user [options] <PACKAGE_OR_COMPONENT> |
옵션 :
|
grant <PACKAGE_PERMISSION> |
응용프로그램에 대한 권한을 승인. 응용프로그램이 이미 선언한 선택적인 권한만이 승인될 수 있음. |
revoke <PACKAGE_PERMISSION> |
응용프로그램에 대한 권한에 대한 승인을 철회. 응용프로그램이 이미 선언한 선택적인 권한에 대해서만 승인이 철회될 수 있음. |
set-install-location <LOCATION> | 기본 설치 위치를 변경함. 위치 값들은 다음과 같다 :
주의 : 이는 디버깅을 위한 용도이다; 이것은 응용프로그램이 깨지거나 다른 원하지 않는 행동을 하도록 만들 수 있다. |
get-install-location | 현재 설치 위치를 반환함. 반환값들을 다음과 같다
|
set-permission-enforced <PERMISSION> [true|false] |
주어진 권한이 강제되어야 하는지를 지정한다. |
trim-caches <DESIRED_FREE_SPACE> |
주어진 가용 공간에 도달하기 위해서 캐시 파일들을 손질한다. |
create-user <USER_NAME> |
주어진 <USER_NAME> 을 사용해 새로운 사용자를 생성하고, 그 사용자의 새로운 식별자를 출력함. |
remove-user <USER_ID> | 주어진 <USER_ID>를 사용해 사용자를 제거하고, 그 사용자와 관련된 모든 데이터를 제거함. |
get-max-users | 장치에 의해 지원되는 최대 사용자 수를 출력함. |
Examing sqlite3 databases from a remote shell
adb remote 쉘에서, 당신은 안드로이드 응용프로그램들에 의해서 생성된 SQLite 데이터베이스들을 관리하기 위해서 sqllite3 명령줄 프로그램을 사용할 수 있다. sqlite3 도구는 많은 유용한 명령들을 포함하고 있다; .dump 는 테이블의 내용을 출력하며, .schema 는 현존 테이블을 위한 SQL CREATE 상태를 출력한다. 이 도구는 SQLite 명령들을 실시간에 실행할 수 있는 기능을 제공하기도 한다.
sqlite3 를 사용하기 위해, 에뮬레이터 인스턴스 상의 remote 쉘로 들어간다. 그리고 나서 sqlite3 명령을 사용해 그 도구를 실행한다. sqlite3 를 실행할 때 당신은 선택적으로 당신이 살펴 보고자 하는 데이터베이스의 전체 경로를 지정할 수 있다. 에뮬레이터/장치 인스턴스들은 SQLite3 데이터베이스들을 /data/data/<package_name>/databases/ 폴더에다가 저장한다.
여기 예제가 있다 :
일단 sqlite3 를 실행하고 나면, 당신은 그 쉘에서 sqlite3 명령들을 제출할 수 있다. adb remote 쉘로 나가고 싶으면, exit 나 CTRL+D 를 사용한다.
UI/Application Exerciser Monkey
몽키는 당신의 에뮬레이터나 장치 상에서 실행되는 프로그램이며, 클릭, 터치, 제스쳐 등과 같은 사용자 이벤트들과 시스템 수준 이벤트들의 의사-랜덤 스트림들을 생성한다. 당신은 몽키를 사용해서 당신이 개발하고 있는 응용프로그램들에 대한 랜덤하지만 약간 반복적인 방식으로 스트레스 테스트를 할 수 있다.
몽키를 사용하는 가장 단순한 방법은 아래 명령을 사용하는 것인데, 그것은 당신의 응용프로그램을 실행하고 500 개의 의사-랜덤 이벤트들을 그것에 보낸다.
몽키를 위한 명령 옵션에 대한 더 많은 정보를 원한다면, 완전한 UI/Application Exerciser Monkey 문서화 페이지를 참조하라.
Other shell commands
이용 가능한 모든 쉘 프로그램들을 열거하기 위해서는 다음과 같은 명령을 사용하라 :
help 는 대부분의 명령들에 대해 이용할 수 있다.
표4 는 좀 더 공용적인 adb 쉘 명령들을 열거한다.
표4. 일부 다른 adb 쉘 명령들.
Shell Command |
Description | Comments |
dumpsys |
스크린에 시스템 데이터를 덤프. | Dalvik Debug Monitor Server( DDMS ) 도구는 당신이 사용하기에 더 쉬운 통합된 디버깅 환경을 제공한다. |
dumpstate | 파일의 상태를 덤프. | |
logcat [options]... [filter-spec]... | 시스템 및 앱 로깅을 이용 가능하게 하고, 결과를 스크린에 출력. | |
dmesg | 커널 디버깅 메시지를 스크린에 출력. | |
start | 에뮬레이터/장치 인스턴스를 시작( 재시작 ). |
|
stop | 에뮬레이터/장치 인스턴스의 실행을 종료. |
Enabling locat logging
안드로이드 로깅 시스템은 시스템 디버그 출력을 수집하고 보기 위한 메커니즘을 제공한다. 다양한 응용프로그램 및 시스템의 일부로부터의 로그들은 일련의 circular buffer 들 안에 수집되는데, 그것들은 logcat 명령에 의해 보여지고 필터링될 수 있다.
당신은 logcat 명령을 사용해 시스템의 로그 버퍼들의 내용을 보고 따라갈 수 있다. 범용적인 용례는 다음과 같다 :
당신은 logcat 명령을 개발 컴퓨터나 에뮬레이터/장치 인스턴스의 remote adb 쉘에서 사용할 수 있다. 개발 컴퓨터에서 로그 출력을 보려면, 다음과 같이 한다 :
그리고 remote adb 쉘에서 로그 출력을 보려면 다음과 같이 한다 :
logcat 명령 옵션들과 filter 명세들에 대한 완전한 정보를 원한다면 Reading and Writing Logs 를 참조하라.
Stopping the adb server
어떤 경우에, 당신은 adb 서버 프로세스를 종료시키고, 그것을 다시 시작하기 원할 것이다. 예를 들어 adb 가 명령에 응답하지 않는다면, 당신은 그 서버를 종료시키고 재시작할 수 있으며, 그것은 그 문제를 해결할 것이다.
adb 서버를 중지하고자 한다면, kill-server 명령을 사용하라. 그리고 나서 당신은 다른 adb 명령을 제출함으로써 그 서버를 재시작할 수 있다.
[ 안드로이드 NDK 프로그래밍 ] [ 보충 ][ 번역 ] ndk-build tool (0) | 2013.04.02 |
---|---|
[ 안드로이드 NDK 프로그래밍 ][ 번역 ] 명령줄에서 안드로이드 프로젝트 관리하기( android 툴 ) (0) | 2013.03.27 |
[ 안드로이드 NDK 프로그래밍 ] Ubuntu 12.10 에서 ndk-build error 127 에 대응 (0) | 2013.03.24 |
Android NDK 개발 환경 : Cygwin 의 개념 (7) | 2013.02.25 |
[ 번역 ] Signing Your Applications( 응용프로그램 서명하기 ) (0) | 2013.02.06 |
[ 안드로이드 NDK 프로그래밍 ] ant install 관련 명령 보충 (2) | 2013.02.06 |
[ 안드로이드 NDK 프로그래밍 ] android 명령 관련 보충 (0) | 2013.02.06 |
[ 안드로이드 NDK 프로그래밍 ] bash_profile 설정과 관련한 보충 (0) | 2013.02.05 |
원문 : http://developer.android.com/tools/publishing/app-signing.html
주의 : 번역이 개판이므로 원문을 참조하세요.
주의 : 허락받고 번역한 것이 아니므로 언제든 내려갈 수 있습니다.
주의 : 가독성을 높이기 위해서 잘 알려진 용어나 발음이 비슷한 용어는 한글로 표기합니다.
Signing Your Applications( 응용프로그램 서명하기 )
안드로이드 시스템은 모든 설치된 응용프로그램들이 응용프로그램의 개발자에 의해 설정된held 개인 키private key 를 가진 인증서certificate 를 사용해 디지털 방식으로 서명될 것을 요구한다. 안드로이드 시스템은 그 인증서를 응용프로그램의 저작자를 식별하고 응용프로그램 사이에서 신뢰 관계를 설정하는데 사용한다. 그 인증서는 사용자가 설치할 수 있는 응용프로그램이 무엇인지를 제어하는데 사용되지는 않는다. 그 인증서는 인증 기관certificate authority에 의해서 서명될 필요는 없다: 안드로이드 응용프로그램을 위해서 자체 서명 인증서를 사용하는 것은 일반적이며 완전히 허용되어 있다.
안드로이드 응용프로그램에 대한 서명을 이해하기 위해서 몇 가지 중요한 점이 있다 :
안드로이드 시스템은 적절히 서명되지 않은 응용프로그램을 설치하거나 실행하지 않을 것이다. 이는 안드로이드 시스템이 실제 디바이스에서 실행되든 에뮬레이터에서 실행되든 상관없이 적용된다. 그렇기 때문에, 당신은 반드시 에뮬레이터나 디바이스 상에서 그것을 실행하거나 디버깅하기 전에 응용프로그램에 대한 서명을 설정해야만 한다.
Signing Process( 서명 절차 )
안드로이드 빌드 절차는 응용프로그램을 빌드하기 위해서 사용하는 빌드 모드에 의존해 다른 서명을 한다. 두 가지 빌드 모드가 있다: 디버그 모드와 릴리스 모드. 당신은 응용프로그램을 개발하고 테스트하고 있는 동안에 디버그 모드를 사용한다. 당신은 사용자에게 직접적으로 배포할 수 있거나 Google Play 와 같은 응용프로그램 마켓에서 배포할 수 있는 릴리스 버전의 응용프로그램을 빌드하고자 할 때 릴리스 모드를 사용한다.
디버그 모드에서 빌드할 때, 안드로이드 SDK 빌드 툴들은 ( JDK 에 포함된 ) Keytool 유틸리티를 사용하여 디버그 키를 생성한다. SDK 빌드 툴들은 디버그 키를 생성하기 때문에, 그것들은 디버그 키의 별명alias과 비밀번호를 알고 있다. 당신이 디버그 모드로 응용프로그램을 컴파일할 때마다, 빌드 툴들은 ( 역시 JDK 에 포함된 ) Jarsigner 유틸리티와 디버그 키를 사용해서 당신의 응용프로그램의 .apk 파일을 서명한다. 그 별명과 비밀번호가 SDK 빌드 툴들에 알려져 있기 때문에, 그 툴들은 당신에게 디버그 키의 별명과 패스워드를 컴파일할 때마다 묻는 작업을 할 필요가 없다.
당신이 릴리스 모드로 빌드할 때, 당신은 자신만의 개인 키를 사용해 당신의 응용프로그램을 서명한다. 만약 당신이 개인 키를 가지고 있지 않다면, 당신은 Keytool 유틸리티를 사용해서 키를 생성할 수 있다. 응용프로그램이 릴리스 모드에서 컴파일될 때, 빌드 툴들은 당신의 개인 키를 Jarsigner 유틸리티와 함께 사용해 당신의 응용프로그램의 .apk 파일을 서명한다. 당신이 사용하는 인증서와 개인키는 당신의 것이기 때문에, 당신은 keystore 와 key alias 를 위한 비밀번호를 제공해야만 한다.
당신이 Eclipse 를 ADT 플러그인과 함께 사용해 응용프로그램을 실행하거나 디버깅하고 있을 때는, 디버그 서명 절차가 자동적으로 수행된다. Ant 빌드 스크립트를 debug 옵션과 함께 사용할 때도, 디버그 서명은 자동적으로 수행된다. 당신은 Eclipse Export Wizard 를 사용하거나 Ant 빌드 스크립트를 수정하고 release 옵션으로 빌드함으로써 릴리스 서명 절차를 자동화할 수 있다.
Signing Strategies( 서명 전략들 )
어떤 관점에서의 응용프로그램 서명은 아마도 당신의 응용프로그램 개발에 접근하는 방식에 영향을 줄 수도 있다. 특히 당신이 여러 개의 응용프로그램을 릴리스할 계획을 가지고 있다면 더욱 그러하다.
일반적으로 모든 개발자들을 위해서 추천되는 전략은 당신의 응용프로그램의 기대 수명 전반에 있어서 같은 인증서를 사용해서 서명하는 것이다. 당신이 그렇게 해야 하는 몇 가지 이유가 있다 :
서명 전략을 결정하는 데 있어서 다른 중요하게 고려해야할 점은 당신의 응용프로그램을 서명하기 위해서 사용할 키의 유효 기한을 설정하는 방법이다.
만약 당신이 단일 응용프로그램을 위한 업그레이드를 지원할 계획을 가지고 있다면, 당신은 당신의 키가 그 응용프로그램의 기대 수명을 초과하는 유효 기한을 가지도록 보장해야만 한다. 25 년 이상의 유효 기한이 추천된다. 당신의 키의 유효 기한이 만료되면, 사용자들은 더 이상 계속해서 새로운 버전의 응용프로그램에 대한 업그레이드를 할 수 없을 것이다.
만약 당신이 여러 개의 분리된 응용프로그램들을 같은 키를 사용해서 서명한다면, 당신은 당신의 키가 모든 응용프로그램의 모든 버전에 대한 기대 수명을 초과하는 유효기한을 가지도록 보장해야만 한다. 이 때 그 응용프로그램들에는 미래에 추가할 수도 있는 의존성있는 응용프로그램들이 포함된다.
만약 당신이 응용프로그램을 Google Play 에서 배포할 계획을 가지고 있다면, 당신이 응용프로그램을 서명하는데 사용한 키는 반드시 2033 년 10 월 22 일 이후에 종료되는 유효 기한을 가져야만 한다. Google Play 는, 새로운 버전이 이용 가능할 때 사용자들이 계속해서 응용프로그램을 업그레이드할 수 있도록 보장하기 위해서, 이 요구사항을 강제한다.
당신의 응용프로그램을 설계할 때, 이러한 점을 유념하고 응용프로그램을 서명하기 위한 적절한 인증서를 확인하기 바란다.
Basic Setup for Signing( 서명을 위한 기본 설정 )
시작하기 전에, Keytool 유틸리티와 Jarsigner 유틸리티가 SDK 빌드 툴들에 대해 이용 가능한지를 확인하라. 두 툴은 모두 JDK 에서 이용할 수 있다. 대부분의 경우에, 당신은 JAVA_HOME 환경 변수를 설정함으로써 이러한 유틸리티들을 찾는 방법을 SDK 빌드 툴들에 알려줄 수 있다. 이를 통해 빌드 툴들은 적절한 JDK 를 참조하게 된다. 그렇지 않으면, 당신은 JDK 버전의 Keytool 과 Jarsigner 을 당신의 PATH 변수에다가 추가할 수 있다.
만약 Java 를 위한 GNU 컴파일러를 원래부터 포함하는 버전의 리눅스 상에서 개발중이라면, 시스템이 JDK 버전의 Keytool 을 사용하고 있는지 확인하라. 만약 Keytool 이 이미 PATH 에 존재한다면, 그것은 /usr/bin/keytool 의 symlink 를 가리키고 있을 것이다. 이 경우, symlink 대상을 확인해 그것이 JDK 의 Keytool 을 가리키는지를 확인하라. 1
Signing in Debug Mode( 디버그 모드에서 서명하기 )
안드로이드 빌드 툴들은 응용프로그램을 더 쉽게 개발하고 디버깅하게 하기 위해서 디버그 서명 모드를 제공한다. 그러면서도 여전히 APK 를 서명하기 위한 안드로이드 시스템 요구사항을 만족시킨다. 응용프로그램을 빌드하기 위해서 디버그 모드를 사용할 때, SDK 툴들은 Keytool 을 실행해서 자동적으로 디버그 키스토어와 키를 생성한다. 그리고 나서 이 디버그 키는 자동적으로 APK 를 서명하기 위해 사용되며, 그래서 당신은 자신의 키를 사용해 패키지를 서명할 필요가 없다.
SDK 툴들은 디버그 키스토어/키 를 미리 결정된 이름/비밀번호 를 사용해 생성한다.
필요하다면 디버그 키스토어/키 의 위치/이름 을 변경하거나 커스텀 디버그 키스토어/키 를 공급할 수 있다. 그러나 모든 커스텀 디버그 키스토어/키 는 반드시 ( 위에 언급된 것처럼 ) 기본 디버그 키와 같은 키스토어/키 이름과 비밀번호를 가져야 한다. ( 그렇게 하기 위해서는 Eclipse/ADT 에서, Windows > Preferences > Android > Build 로 이동하라. )
주의 : 당신은 디버그 인증으로 서명된 응용프로그램을 대중에게 릴리스할 수 없다.
Eclipse Users
당신이 Eclipse/ADT 에서 개발하고 있다면 ( 그리고 Basic Setup for Signing 에서 기술된 것처럼 Keytool 과 Jarsigner 를 설정했다면 ), 디버그 모드에서의 서명은 기본적으로 활성화된다. 당신이 응용프로그램을 실행하거나 디버그할 때, ADT 는 .apk 파일을 디버그 인증서를 사용해 서명하고, 패키지 상에 zipalign 을 실행하고, 그 다음에 선택된 에뮬레이터나 연결된 디바이스 상에 그것을 설치한다. 당신이 해야할 특별한 일은 없으며, 제공된 ADT 가 Keytool 에 대한 접근권을 가진다.
Ant Users
만약 .apk 파일을 빌드하기 위해 Ant 를 사용하고 있다면, ant 명령을 debug 옵션과 함께 사용함으로써 디버그 서명 모드가 활성화된다( 당신이 android 툴을 사용해서 생성한 build.xml 파일을 사용하고 있다고 가정한다 ). 당신이 and debug 를 실행해서 응용프로그램을 컴파일할 때, 빌드 스크립트는 키스토어/키 를 생성하며, 당신을 위해서 APK 에 서명한다. 그리고 나서 스크립트는 API 를 zipalign 툴을 사용해 정렬한다. 당신이 해야 할 일은 없다. 더 많은 정보를 원한다면 Building and Running Apps on the Command Line 을 읽어 보라.
Expiry of the Debug Certificate( 디버그 인증서 만료 )
디버그 모드에서 ( Eclipse/ADT 와 Ant 빌드의 기본 설정 ) 응용프로그램을 서명하기 위해서 사용된 자체 서명 인증서는 그것의 생성일로부터 1 년의 만료일을 가진다.
인증서가 만료되면, 당신은 빌드 에러를 만나게 될 것이다. Ant 빌드에서 에러는 다음과 같다 :
Eclipse/ADT 에서, 당신은 안드로이드 콘솔에서 비슷한 에러를 볼 수 있다.
이 문제를 해결하기 위해서는 단순하게 debug.keystore 파일을 제거하기만 하면 된다. AVD 들을 위한 기본 저장소 위치는 OS X 와 Linux 에서는 ~/.android/ 이고, Windows XP 에서는 C:\Documents and Settings\<user>\.android\ 이고, Windows Vista 와 Windows 7 에서는 C:\Users\<user>\.android\ 이다.
다음에 빌드를 하면, 빌드 툴들은 새로운 키스토어와 디버그 키를 생성할 것이다.
당신의 개발 머신이 non-Gregorian locale 을 사용하고 있다면, 빌드 툴들은 아마도 이미 만료된 디버그 인증서를 생성할지도 모른다. 그래서 당신은 응용프로그램을 컴파일하려고 시도할 때마다 에러를 만나게 될 것이다. 이를 우회하기 위한 정보는 문제 해결 토픽인 I can't compile my app because the build tools generated an expired debug certificate 를 참조하라.
Signing in Release Mode( 릴리스 모드에서 서명하기 )
당신의 응용프로그램을 다른 사용자에게 릴리스하기 위한 준비가 되었다면, 당신은 반드시 다음과 같은 일을 수행해야만 한다 :
만약 ADT 플러그인을 사용해 Eclipse 에서 개발중이라면, 컴파일, 서명, 정렬 프로시저를 수행하기 위해서 Export Wizard 를 사용할 수 있다. Export Wizard 는 심지어 당신이 새로운 키스토어와 개인 키를 그 과정에서 생성할 수 있도록 허용한다. 그래서 당신이 Eclipse 를 사용한다면, Compile and sign with Eclipse ADT 는 건너 뛰어도 된다.
1. Obtain a suitable private key( 적절한 개인 키 획득하기 )
응용프로그램에 서명을 하기 위한 준비에서, 당신은 먼저 서명할 적절한 개인키를 가지고 있다는 것을 확신해야만 한다. 적절한 개인 키는 다음과 같은 것이다 :
그 키는 아마 자체 서명될 것이다. 만약 당신이 적절한 키를 가지고 있지 않다면, 반드시 Keytool 을 사용해서 생성해야만 한다. Basic Setup 에서 기술된 것처럼, 당신이 가진 Keytool 이 이용 가능한지 확인하라.
자체 서명된 키를 Keytool 을 사용해 생성하기 위해서는, keytool 명령을 사용하는데, 아래에 열거된 옵션들을 넘긴다( 필요하면 다른 것을 넘길 수 있다 ).
경고 : 개인키를 안전하게 보관하라. Keytool 을 실행하기 전에, 당신의 키를 안전하게 보관하는 방법과 그것이 당신과 사용자들에게 매우 중요한 이유에 대한 논의를 위해 Securing Your Private Key 를 반드시 읽어라. 특히, 당신이 키를 생성하고 있을 때, 당신은 키스토어와 키 모두를 위해 강한 비밀번호strong password를 선택해야만 한다.
Keytool Option | Description |
-genkey |
키 쌍을 생성한다( 공용 키, 개인 키 ) |
-v | verbose 출력을 활성화한다. |
-alias <alias_name> | 키에 대한 별명. 8 개의 문자만이 사용된다. |
-keysize <size> | 각각의 생성된 키의 크기( bits ). Keytool 은 1024 bits 의 기본 키 크기를 사용한다. 일반적으로 우리는 2048 bits 이상을 사용하는 것을 추천한다. |
-dname <name > | 누가 키를 생성했는지를 기술하는 구별 가능한 이름. 이 값은 자체 서명 인증서에서 발행인issuer과 제목 필드로 사용된다. 커맨드 라인에서 이 옵션을 지정할 필요는 없다. 만약 제공되지 않으면, Jarsigner 는 당신에게 구별 가능한 이름 필드들( CN, OU 등 )을 입력하기 위해 당신에게 묻는다. |
-keypass <password> |
키에 대한 비밀번호. 보안 예방책으로, 커맨드 라인에서 이 옵션을 포함하지 말라. 만약 제공되지 않으면, Keytool 이 비밀번호를 입력하기 위해 당신에게 묻는다. 이러한 방식으로, 당신의 비밀번호가 당신의 쉘 히스토리에 저장되지 않게 된다. |
-validity <valdays> | 키를 위한 일단위 유효 기한. 주의 : 10000 이상의 값을 추천한다. |
-keystore <keystorename>.keystore |
개인 키를 포함하는 키스토어를 위한 이름. |
-storepass <password> | 키스토어를 위한 비밀번호. 보안 예방책으로, 커맨드 라인에서 이 옵션을 포함하지 말라. 만약 제공되지 않는다면, Keytool 이 비밀번호를 입력하기 위해 당신에게 묻는다. 이러한 방식으로, 당신의 비밀번호가 쉘 히스토리에 저장되지 않게 된다. |
-keyalg <alg> | 키를 생성할 때 사용할 암호화 알고리즘. DSA 와 RSA 가 지원된다. |
아래에 개인 키를 생성하는 keytool 명령의 예가 나와 있다 :
위의 예제 명령을 실행하면, keytool 은 키스토어와 키에 대한 비밀번호를 제공하고 키를 위한 구별 가능한 이름 필드들을 제공하기 위해 당신에게 묻는다. 그리고 나서 그것은 my-release-key.keystore 라는 파일로 키스토어를 생성한다. 그 키스토어와 키는 당신이 입력한 비밀번호로 보호된다. 그 키스토어는 단일 키와 10000 일 동안의 유효 기한을 포함한다. 별명은 당신이 나중에 응용프로그램을 서명할 때 이 키스토어를 참조하기 위해서 사용하게 될 이름이다.
Keytool 에 대한 더 많은 정보를 원한다면, http://docs.oracle.com/javase/6/docs/technotes/tools/windows/keytool.html 에 있는 문서를 참조하라.
2. Compile the application in release mode( 릴리스 모드에서 응용프로그램 컴파일하기 )
사용자에게 응용프로그램을 릴리스하기 위해서, 당신은 그것을 릴리스 모드로 컴파일해야만 한다. 릴리스 모드에서, 컴파일된 응용프로그램은 기본적으로 서명되지 않으며, 당신은 개인 키를 사용해 그것을 서명할 필요가 있을 것이다.
주의 : 당신은 서명되지 않은 응용프로그램이나 디버그 키로 서명된 응용프로그램을 릴리스할 수 없다.
With Eclipse
서명되지 않은 APK 를 Eclipse 에서 익스포트하기 위해서는, Package Explorer 에서 프로젝트를 오른쪽 클릭하고, Android Tools > Export Unsigned Application Package 를 선택하라. 그리고 나서 서명되지 않은 APK 를 위한 파일 위치를 지정하라. ( 그렇지 않으면, AndroidManifest.xml 파일을 Eclipse 에서 열어서, Manifest 탭을 선택하고, Export an unsigned APK 를 클릭하라. )
당신은 Export Wizard 를 사용해서 컴파일과 서명을 합칠 수 있다. Compiling and signing with Eclipse ADT 를 참조하라.
With Ant
당신이 Ant 를 사용하고 있다면, ant 명령을 release 옵션과 함께 사용해 릴리스 모드를 활성화할 수 있다. 예를 들어, 만약 당신이 build.xml 을 포함하고 있는 디렉토리에서 Ant 를 실행하고 있다면, 그 명령은 다음과 같을 것이다 :
기본적으로, 빌드 스크립트는 응용프로그램 APK 를 서명하지 않은 채로 컴파일한다. 프로젝트의 bin/ 에서의 출력 파일은 <your_project_name>-unsigned.apk 일 것이다. 응용프로그램 APK 는 여전히 서명되지 않았기 때문에, 당신은 반드시 수동적으로 개인 키를 사용해 서명하고 zipalign 을 사용해 정렬해야만 한다.
그런데 당신이 키스토어와 키 별명의 이름에 대한 경로를 프로젝트의 ant.properties 파일에다가 제공해 놓았다면, Ant 빌드 스크립트는 서명과 정렬을 수행할 수 있다. 이 정보를 제공하면, 빌드 스크립트는 ant release 를 수행할 때 당신의 키스토어와 별명 비밀번호를 입력받는 창을 띄운다. 그것은 패키지에 서명을 하고 그것을 정렬할 것이다. bin/ 의 최종 출력 파일은 <your_project_name>-release.apk 가 될 것이다. 이 단계들이 자동화되면, 당신은 3 과 5 의 수동 프로시저를 건너 뛸 수 있다. ant.properties 파일에 키스토어와 별명을 지정하는 방법에 대해서 배우고 싶다면, Building and Running Apps on the Command Line 을 참조하라.
3. Sign your application with your private key( 개인 키로 응용프로그램 서명하기 )
서명될 준비가 된 응용프로그램 패키지를 가지고 있을 때, 당신은 Jarsigner 툴을 사용해서 그것에 서명할 수 있다. Basic Setup 에서 설명했듯이, 당신의 머신에서 이용 가능한 Jarsigner 를 가지고 있는지 확인하라. 또한 개인키를 포함하는 키스토어가 이용 가능한지 확인하라.
응용프로그램에 서명하기 위해서, 당신은 Jarsigner 를 실행하는데, 응용프로그램의 APK 와 APK 를 서명하기 위한 개인 키를 포함하는 키스토어를 모두 참조하게 된다. 아래 표는 당신이 사용할 수 있는 옵션을 보여 준다.
Jarsigner Option | Description |
-keystore <keystore-name>.keystore |
개인 키를 포함하는 키스토어의 이름. |
-verbose | verbose 출력을 가능하게 함. |
-sigalg | APK 를 서명하는데 사용하기 위한 서명 알고리즘의 이름. MD5withRSA 를 사용하라. |
-digestalg | APK 의 엔트리들을 처리하는 과정에 사용하게 될 message digest algorithm. SHA1 을 사용하라. |
-storepass <password> |
키스토어를 위한 비밀번호. 보안 예방책으로, 당신이 보안 컴퓨터에서 작업하고 있지 않은 한은 커맨드 라인에서 이 옵션을 포함하지 말라. 만약 제공되지 않으면, Jarsigner 가 비밀번호를 입력하기 위해 당신에게 묻는다. 이러한 방식으로, 당신의 비밀번호가 당신의 쉘 히스토리에 저장되지 않게 된다. |
-keypass <password> |
개인 키를 위한 비밀번호. 보안 예방책으로, 당신이 보안 컴퓨터에서 작업하고 있지 않은 한은 커맨드 라인에서 이 옵션을 포함하지 말라. 만약 제공되지 않으면, Jarsigner 가 비밀번호를 입력하기 위해 당신에게 묻는다. 이러한 방식으로, 당신의 비밀번호가 당신의 쉘 히스토리에 저장되지 않게 된다. |
아래에 위의 예제에서 생성된 키스토어를 사용해 my_application.apk 라는 응용프로그램 패키지를 서명하기 위해 Jarsigner 를 사용하는 방법이 있다.
위의 예제를 실행하면, Jarsigner 는 키스토어와 키에 대한 비밀번호를 제공하기 위해 당신에게 묻는다. 그리고 나서 현재의 APK 를 수정하며, 그것은 APK 가 이제 서명되었음을 의미한다. 다른 키를 사용해 여러 번 APK 에 서명할 수 있다는 것에 주목하라.
주의 : JDK 7 부터, 기본 서명 알고리즘이 변경되었는데, APK 에 서명을 할 때 당신이 서명 알고리즘과 다이제스트 알고리즘을( -sigalg 와 -digestalg ) 지정하도록 요구하고 있다.
서명된 APK 를 검증하기 위해서, 당신은 다음과 같은 명령을 사용할 수 있다 :
만약 APK 가 적절하게 서명되었다면, Jarsigner 는 "jar verified" 를 출력한다. 만약 좀 더 세부적인 것을 우너한다면, 다음 명령들을 시도해 볼 수 있다 :
혹은
위에서 -certs 옵션을 가진 명령은 누가 키를 생성했는지를 기술하는 "CN=" 라인을 보여 줄 것이다.
주의 : 만약 당신이 "CN=Android Debug" 라는 것을 보게 된다면, 이것은 APK 가 안드로이드 SDK 에 의해 생성된 디버그 키로 서명되었음을 의미한다. 만약 응용프로그램을 릴리스하려는 의도라면, 당신은 반드시 디버그 키 대신에 개인 키를 사용해서 서명해야만 한다.
Jarsigner 에 대한 더 많은 정보를 원한다면, http://docs.oracle.com/javase/6/docs/technotes/tools/windows/jarsigner.html 의 문서를 참조하라.
4. Align the final APK package( 최종 APK 패키지 정렬하기 )
개인키로 서명된 APK 를 확보했으면, zipalign 을 파일에 대해 실행하라. 이 툴은 모든 비압축 데이터가 파일의 시작부분에 대해 상대적인 특별한 바이트에 정렬되는 것을 보장한다. 4 바이트 경계에서 정렬을 보장하는 것은 디바이스 상에서 설치될 때 성능 최적화를 제공한다. 정렬되어 있다면, 심지어 그것들이 정렬 제약을 가진 이진 데이터를 포함하더라도, 안드로이드 시스템은 모든 데이터를 패키지로부터 복사하는 대신에 파일을 mmap() 을 사용해서 읽어들일 수 있다. 이것의 효과는 응용프로그램을 실행함으로써 소비되는 RAM 의 양을 줄이는 것이다.
zipalign 툴은 안드로이드 SDK 와 함께 제공되며, tools/ 디렉토리 내부에 있다. 서명된 APK 를 정렬하려면, 다음을 실행하라 :
-v 플래그는 ( 선택적인 ) verbose 출력을 켠다. 4 는 바이트 정렬( 4 아닌 다른 값을 사용하지 말라 )이다. 첫 번째 인자는 당신의 서명된 .apk 파일( 입력 )이며, 두 번째 파일은 대상 .apk 파일( 출력 )이다. 만약 당신이 현존하는 APK 를 override 했다면, -f 플래그를 추가하라.
주의 : 당신의 입력 APK 는 zipalign 을 사용해 패키지를 최적화하기 전에 반드시 개인 키로 서명되어 있어야만 한다. 만약 zipalign 을 사용한 후에 서명을 하면, 그것은 정렬을 취소할 것이다.
더 많은 정보를 원한다면, zipalign 툴에 대해 읽어 보라.
Compile and sign with Eclipse ADT( Eclipse ADT 를 사용해 컴파일하고 서명하기 )
만약 Eclipse 를 ADT 플러그인과 함께 사용하고 있다면, Export Wizard 를 사용해서 서명된 APK 를 익스포트할 수 있다( 그리고 필요하면 키스토어도 새로 생성할 수 있다 ). Export Wizard 는 Keytool 과 Jarsigner 와의 모든 상호작용을 당신을 위해 해 준다. 이는 위에서 언급했던 컴파일, 서명, 정렬 등을 위한 수동 프로시저들을 수행하는 대신에 GUI 를 사용해 패키지에 서명할 수 있도록 해 준다. 일단 마법사가 당신의 패키지를 컴파일하고 서명하면, 그것은 zipalign 을 사용해 패키지 정렬도 수행한다. Export Wizard 는 Keytool 과 Jarsigner 를 모두 사용하기 때문에, 당신은 당신의 컴퓨터에서 그것에 접근할 수 있다는 것만 보장하면 된다; Basic Setup for Signing 에서 언급했듯이...
Eclipse 에서 서명된 APK 를 생성하기 위해서는 :
Securing Your Private Key( 개인키 보호하기 )
개인 키의 보안을 유지하는 것은 당신이나 사용자에게 있어서 매우 중요하다. 만약 누군가가 당신의 키를 사용하도록 허용하거나, 당신이 키스토어와 비밀번호를 서드 파티가 찾고 이용할 수 있는 보호되지 않은 위치에다가 남겨 두게 되면, 당신의 저작관과 사용자에 대한 신뢰가 위태롭게 된다.
서드 파티가 당신의 인지나 승인없이 당신의 키를 취할 수 있다면, 그 사람은 당신의 원본 응용프로그램들을 악의적으로 대체하고 그것들을 변질시키는 응용프로그램들을 서명하거나 배포할 수 있다. 또한 그러한 사람은 당신의 신분을 이용해 다른 응용프로그램이나 시스템 자체를 공격하거나 사용자의 데이터를 변질시키거나 훔치는 응용프로그램들을 서명하거나 배포할 수도 있다.
당신의 개발자로서의 평판은 그 키가 만료될 때까지 항상 적절하게 개인 키를 보호하느냐에 달려 있다. 여기 키 보안을 지키기 위한 몇 가지 팁들이 있다 :
일반적으로, 당신이 키를 생성하고 사용하고 저장할 때, 일반적인 예방책을 따른다면, 그것은 보호된 상태로 남아 있을 수 있을 것이다.
[ 안드로이드 NDK 프로그래밍 ] [ 보충 ][ 번역 ] ndk-build tool (0) | 2013.04.02 |
---|---|
[ 안드로이드 NDK 프로그래밍 ][ 번역 ] 명령줄에서 안드로이드 프로젝트 관리하기( android 툴 ) (0) | 2013.03.27 |
[ 안드로이드 NDK 프로그래밍 ] Ubuntu 12.10 에서 ndk-build error 127 에 대응 (0) | 2013.03.24 |
Android NDK 개발 환경 : Cygwin 의 개념 (7) | 2013.02.25 |
[ 번역 ] Android Debug Bridge (5) | 2013.02.10 |
[ 안드로이드 NDK 프로그래밍 ] ant install 관련 명령 보충 (2) | 2013.02.06 |
[ 안드로이드 NDK 프로그래밍 ] android 명령 관련 보충 (0) | 2013.02.06 |
[ 안드로이드 NDK 프로그래밍 ] bash_profile 설정과 관련한 보충 (0) | 2013.02.05 |
책의 71 페이지에서는 다음과 같은 명령어를 사용해서 APK 를 만들라고 하고 있다.
현재 1.8.4 버전의 ant 를 설치했는데, 이것은 구체적으로 빌드 타겟을 지정할 것을 요구한다.
그러므로 위에서 설명하고 있는 것처럼 아래와 같은 형식으로 호출해야 한다.
[ 안드로이드 NDK 프로그래밍 ] [ 보충 ][ 번역 ] ndk-build tool (0) | 2013.04.02 |
---|---|
[ 안드로이드 NDK 프로그래밍 ][ 번역 ] 명령줄에서 안드로이드 프로젝트 관리하기( android 툴 ) (0) | 2013.03.27 |
[ 안드로이드 NDK 프로그래밍 ] Ubuntu 12.10 에서 ndk-build error 127 에 대응 (0) | 2013.03.24 |
Android NDK 개발 환경 : Cygwin 의 개념 (7) | 2013.02.25 |
[ 번역 ] Android Debug Bridge (5) | 2013.02.10 |
[ 번역 ] Signing Your Applications( 응용프로그램 서명하기 ) (0) | 2013.02.06 |
[ 안드로이드 NDK 프로그래밍 ] android 명령 관련 보충 (0) | 2013.02.06 |
[ 안드로이드 NDK 프로그래밍 ] bash_profile 설정과 관련한 보충 (0) | 2013.02.05 |
책의 70 페이지에서는 다음과 같이 project 를 설정하라고 이야기하고 있다.
필자는 윈도우 환경이기 때문에 cygwin 에서 다음과 같이 실행했다.
error 를 보면 알 수 있듯이 "-p" 옵션은 프로젝트가 있는 디렉토리의 경로를 지정할 것을 요구한다.
그러므로 현재 경로인 "./" 을 넣어서 해결했다.
[ 안드로이드 NDK 프로그래밍 ] [ 보충 ][ 번역 ] ndk-build tool (0) | 2013.04.02 |
---|---|
[ 안드로이드 NDK 프로그래밍 ][ 번역 ] 명령줄에서 안드로이드 프로젝트 관리하기( android 툴 ) (0) | 2013.03.27 |
[ 안드로이드 NDK 프로그래밍 ] Ubuntu 12.10 에서 ndk-build error 127 에 대응 (0) | 2013.03.24 |
Android NDK 개발 환경 : Cygwin 의 개념 (7) | 2013.02.25 |
[ 번역 ] Android Debug Bridge (5) | 2013.02.10 |
[ 번역 ] Signing Your Applications( 응용프로그램 서명하기 ) (0) | 2013.02.06 |
[ 안드로이드 NDK 프로그래밍 ] ant install 관련 명령 보충 (2) | 2013.02.06 |
[ 안드로이드 NDK 프로그래밍 ] bash_profile 설정과 관련한 보충 (0) | 2013.02.05 |
책의 35 페이지에서는 ".bash_profile" 이라는 파일에 다음과 같은 식으로 스크립트를 추가할 것을 요구하고 있다.
환경변수를 가지고 올 때 MS_DOS 형식으로 인식하는 것을 막기 위함이라고 하는데, 저자가 설치한 것이 어떤 버전인지는 모르겠지만, 현재 설치한 버전( 1.7.17-1 )에서는 그런 문제가 자동으로 해결되어 있는 것 같다.
실제로 저런 스크립트를 추가하게 되면 오히려 제대로 동작하지 않는다.
[ 안드로이드 NDK 프로그래밍 ] [ 보충 ][ 번역 ] ndk-build tool (0) | 2013.04.02 |
---|---|
[ 안드로이드 NDK 프로그래밍 ][ 번역 ] 명령줄에서 안드로이드 프로젝트 관리하기( android 툴 ) (0) | 2013.03.27 |
[ 안드로이드 NDK 프로그래밍 ] Ubuntu 12.10 에서 ndk-build error 127 에 대응 (0) | 2013.03.24 |
Android NDK 개발 환경 : Cygwin 의 개념 (7) | 2013.02.25 |
[ 번역 ] Android Debug Bridge (5) | 2013.02.10 |
[ 번역 ] Signing Your Applications( 응용프로그램 서명하기 ) (0) | 2013.02.06 |
[ 안드로이드 NDK 프로그래밍 ] ant install 관련 명령 보충 (2) | 2013.02.06 |
[ 안드로이드 NDK 프로그래밍 ] android 명령 관련 보충 (0) | 2013.02.06 |
울퉁불퉁에 명암 단계가 부드럽게 이어지지 않는다.
너무 선을 많이 쓰는 느낌도...
강사가 그린걸 보면 오히려 선사이에 빈틈이 많이 보인다.
명암 단계 연습을 좀 해야 할 듯하다.
오늘 동영상에서 강사가 "스트레스 받으면서 그리지 마세요" 라고 하던데, 안 받을 수가 있나 ㅠㅠ
기존의 그림에 덧칠하고 수정해서 반사광이랑 손잡이 반사를 표현하려고 했는데...
반사광 표현은 제대로 안 되고 지저분해지기만 했다.
Shading 만으로 lighting 을 표현하려고 하니까 명암단계 표현이라든가 참 어렵다.
강사는 반사광같은 것을 표현하기 위해서 상당히 진한 색을 사용하는데, 나는 겁이 많아서인지 진한선이 안 나온다.
색 조절이 잘 안 되고 있다.
그래도 컵인지는 알 수 있을 것 같으니 다행이다. ㅡㅡ;;
명암 단계 조정하는 연습을 좀 많이 해야겠다.
내일 덧칠해서 더 그려 봐야겠다.
좋아지는 것 같다가 나빠지는 것 같다가 잘 모르겠다.
연습만이 답이겠지.
날짜가 제대로 안 찍혔네... 1월 20 일에 작업하고 오늘 조금 마무리.
마무리가 사족이라는 느낌 ㅠㅠ
확실히 종이가 바뀌니 그리는 감이 많이 다르다.
거친 종이에서는 색은 더 잘 먹는 것 같고 얇은 선이 잘 나오지 않는 듯한 느낌이다.
일단 선치기가 잘 안 되고 있고, 빛이 들어 오는 것에 대한 감이 제대로 안 잡힌 것 같다.
더 많은 연습이 필요하다. 기본 도형들을 더 많이 그려 봐야겠다.
왠지 갈 수록 퇴보하는 느낌이랄까... 괴롭다 ㅠㅠ
세로선이 제대로 잘 그어지지 않는다.
확실히 종이 질이 많은 영향을 주는 것 같다.
표면이 너무 매끈하니까 음영차이를 내기가 힘들고, 연필도 더 많이 다른 방향으로 미끄러지는 기분이다.
게다가 선이 얇았다 굵었다 지 맘대로다.
명장은 도구탓을 안 한다는데 역시 나는 명장이 되기는 글렀나보다.
내일은 다른 종이로 해 봐야겠다.
한 일주일 동안은 술마시고 아키에이지하고 그러느라 제대로 그림을 못 그렸다.
저번에 벽돌 하다가 남은게 있어서 오늘 완성했다. 원래는 더 세부적으로 그려야 하는데 아직까지는 세부적인 표현은 잘 안 된다.
그냥 양감을 익히려고 노력하고 있다.
문제는 동영상 강좌에서 선생이 그리는 거랑 사진이랑 너무 조명이 달라서 어떻게 그려야 할지 헷갈린다는 것이다.
사실적인 조명을 생각하고 그리면 뭔가 좀 안 맞는다는...
간단한 정육면체 하나 그리는 거지만 너무 힘들었다. ㅎㅎㅎ.
그래도 시간이 지나면 지날 수록 좀 더 선긋는데 익숙해지는 것 같다.
지금까지 선도 평행하지 않고 빈틈도 너무 많고 굵기도 제 멋대로인데 그래도 1월 6일에 그린 것은 많은 개선된 듯 하다.
그리고 어깨도 덜 아프다 ㅎㅎㅎ.
역시 연습이 생명이다.
근데 아직까지도 2012 년이라고 쓰는 습관을 버리지 못했다 ㅠㅠ.
원문 : How Do Those Funky Placeholders Work?
주의 : 허락받고 번역한 것이 아니므로 언제든지 내려갈 수 있습니다.
주의 : 번역이 개판이므로 이상하면 원문을 참조하세요.
주의 : 가독성을 높이기 위해서 발음이 비슷하거나 잘 알려진 용어는 한글로 표기합니다.
MPL 을 하다가 보면 가장 이해가 안 되는 것이 자리표 표현식( placeholder expression )이다. 아주 간단한 형태의 자리표 표현식같은 경우에는 그나마 이해가 가지만, 조금만 복잡해져도 정신이 안드로메다로 가 버린다.
"C++ Template Metaprogramming" 의 내용 중에 다음과 같은 코드가 있다. 이해가 가는가?
나름 자리표 표현식에 대해서 이해했다고 생각했었는데, 필자도 쉽게 이해할 수가 없었다. 그래서 공부도 하는 겸해서 자리표 표현식과 관련한 글을 번역해 보기로 했다.
How Do Those Funky Placeholders Work?
요즘 C++ 표준 함수 binder 들은 정말로 사용하기 어렵다. Chris Gibson 은 Boost 의 대안의 비밀을 보여 준다. 그것은 더욱 낫고 마법같다.
새로운 코딩 기법에 대해서 배우고 그것을 작업하면서 사용하려고 할 때마다, 부서 전반에서 그것이 얼마나 빠르게 받아들여지는지 확인하는 것은 흥미롭다. 널리 전파되는 가장 빠른 것 중의 하나는 boost bind 라이브러리이다. 표준 파이브러리의 bind1st 나 bind2nd 적응자( adapter )들보다 훨씬 사용하기 수비고 훨씬 유연하다. 일단 재미있게 보이는 자리표( placeholder )를 이해하게 되면, bind 라이브러리는 사용하기에 우아하고 단순하다. 그리고 초기의 노력이 보상받게 된다. 당신의 코드는 깔끔해지며, 이해하기 쉬워지며, 빠르게 검토하기 쉬워지며, 빠르게 테스트할 수 있게 된다. 그것은 버그를 포함할 가능성이 더 적으며 아마도 더욱 효율적일 것이다.
내 경험상 평균적인 개발자들은, 물론 당신을 말하는 것은 아니고 나는 확실히 아니다, bind 라이브러리를 처음 사용할 때 아마도 너무 많거나 너무 적거나 잘못된 자리표를 사용할 것이다; 그리고 적어도 한 군데는 잘못된 위치에 그것들을 배치할 것이다. 이런 것들은 여러 페이지의 컴파일 에러들을 발생시킬 것이다. 그리고 나서 평균적인 개발자들은 그것이 너무 어렵다고 생각해서 템플릿은 악마의 조화라고 판단할 것이다. 그리고 그들은 매뉴얼을 읽는데 시간을 소비하지 않고, 그저 그것이 작동하기만을 원할 것이다. So they hand code a solution instead and decide to do it properly before review or release, which in all probability never happens.
그러므로 나는 bind 라이브러리가 직관적인지 그렇지 않은지 판단할 수 없다. 일단 이해하고 나면 직관적이다. but doesn't intuitive mean you don't need to get the hang of it? Can it be true that the more you use the bind library the more intuitive it gets?
일단 개발자들이 그것을 이해하고 나면 언제나 다음과 같이 질문한다. "그런데 그 멋진 자리표는 어떻게 작동하는 거죠?". 이상적인 세계에서는 당신은 라이브러리의 세부사항을 구현하는 것에 관심을 가지지 않을 것이며, 당신은 그냥 그것을 사용하면 될 것이다. 그러나 무대 뒤에서 무슨 일이 벌어지고 있는지 이해하는 것은 몇 가지 이유때문에 유용하다. 당신이 오타를 쳤을 때 평균적인 컴파일러가 제공하는 에러 메시지를 확인하면, 어떤 일들이 벌어지고 있는지 이해하는 데 큰 도움이 된다. 두 번째로 전문가에 의해 개발된 설계를 공부하는 것은 항상 유익하며 당신의 설계를 개선하는데 도움이 될 수 있다. 마지막으로 거의 대부분의 개발자들은 당연히 호기심이 많고, 자리표 구문을 마음에 들어 하면 보통 그것이 작동하는 방식에 대해 알기를 원한다.
이 기사에서는 bind 라이브러리의 자리표가 작동하는 방식에 대해 설명하려고 하는데, 매우 기본적인 bind 라이브러리를 만들 것이다. 그것은 그다지 대단하지 않을 것이지만, 당신의 궁금증을 만족시켜주기에는 충분할 것이라 생각한다. 예제들은 무엇보다도 명확성을 중시하며, 효율성, const 정확성, volatility 등과 같은 다른 이슈들은 고려되지 않는다. 함수 반환 형식들도 고려되지 않으며 void 라고 가정된다는 것에 주의하라.
A quick recap
당신이 widget 컬렉션을 가지고 있으며 당신은 각각에 대해 어떠한 동작을 수행하기를 원하고 있다고 가정하자; 당신은 단순히 다음과 같이 작성할 것이다 :
for_each 알고리즘은 단항 함수( unary function )를 세 번째 매개 변수로 취하는데, 그것은 범위 내의 각 반복자( iterator ) 당 한 번씩 호출되며, 참조해제된 반복자( 역주 : 반복자가 참조하고 있는 실제 값 )를 단항 함수의 단일 인자로 넘긴다( 아래를 보라 ). 우리의 대상 함수는 세 개의 매개 변수를 가지는데, 그것은 두 개의 문제를 가지고 있다 :
매개 변수의 개수가 다른 문제를 해결하는 것은 소프트웨어 공학의 근본 정리( Fundametal Theory of Software Engineering )을 적용하고 알고리즘과 대상 함수 간에 간접층( level of indirection )을 추가함으로써 수행된다. 간접층은 오브젝트의 형태를 취하며, 그것을 바인더( binder )라고 부르도록 하자. 바인더의 역할은 대상 함수의 인터페이스를 호출하는 알고리즘의 인터페이스를 받아들이는( adapt ) 것이다. 바인더는 for_each 에 의해 호출될 수 있다. 왜냐하면 그것은 단항 연산자 () 를 가지고 있기 때문이다. 그리고 바인더는 대상 함수를 호출할 수 있다. 왜냐하면 그것은 대상 함수에 대한 포인터와 두 개의 부가적인 인자를 생성자에서 공급받기 때문이다.
DoSomething 의 세 매개 변수들 중의 어떤 것이 widget 이어야 하는지 지정하는 것이 자리표가 오게 되는 곳이다. bind 라이브러리를 사용해서 우리는 이를 단순화할 수 있다 :
bind 함수는 네 개의 인자들을 받는다 : 대상 함수인 DoSomething 의 주소, Gadget 오브젝트, Gizmo 오브젝트, 자리표 _1. bind 에 대한 두 번째, 세 번째, 네 번째 인자의 순서는 대상 함수에 대한 인자의 순서와 같다는 데 주목하라. 자리표는 for_each 에 의해 단항 함수에 넘겨지는 인자의 위치를 지시한다. 만약 DoSomething 의 시그너쳐( signature )가 widget 을 두 번째 매개 변수로 기대했다면, 우리는 다음과 같이 작성해야할 것이다 :
C++ Template Metaprogramming 실습 과제 2-6 풀이 (0) | 2012.12.31 |
---|---|
C++ Template Metaprogramming 실습 과제 4-5 풀이 (0) | 2012.12.28 |
C++ Template Metaprogramming 실습 과제 4-4 풀이 (0) | 2012.12.17 |
C++ Template Metaprogramming 실습 과제 4-3 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-2 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-1 풀이 (0) | 2012.12.12 |
C++ Template MetaProgramming 실습 과제 4-0 풀이 (0) | 2012.12.10 |
C++ Template MetaProgramming 실습 과제 3-7 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-6 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-5 풀이 (0) | 2012.11.29 |
원문 : C++ Modifier Types
주의 : 번역이 개판이므로 원문을 참조하세요.
주의 : 허락받고 번역한 것이 아니기 때문에 언제든 내려갈 수 있습니다.
주의 : 가독성을 높이기 위해 잘 알려진 용어나 발음이 비슷한 용어는 한글 표기합니다.
C++ Modifier Types
C++ 은 char, int, double data type 앞에 modifier 를 가질 수 있도록 허용한다. Modifier 는 base type 의 의미를 수정하는데 사용되며, 그래서 다양한 상황에 대한 요구를 더 정확하게 만족시킨다.
그 data type modifier 의 리스트는 아래와 같다 :
signed, unsigned, long, short 는 integer base type 들에 적용될 수 있다. 부가적으로 signed 와 unsigned 는 char 에 적용될 수 있으며, long 은 double 에 적용될 수 있다.
signed 와 unsigned 는 long 이나 short 앞에 사용될 수도 있다. 예를 들면 unsigned long int 이다.
C++ 은 unsigned, short, long 의 integer 를 선언하기 위한 단축 표기를 허용한다. 당신은 int 없이 단순히 unsigned, short, long 만을 사용할 수 있다. int 는 내포되어 있다. 예를 들어 다음의 두 문장은 둘 다 unsigned integer 변수를 선언한다.
signed 와 unsigned 가 C++ 에 의해 해석되는 방식의 차이를 이해하기 위해서는, 다음과 같은 짧은 프로그램을 실행해 보면 된다 :
프로그램이 실행되면, 출력은 다음과 같다.
-15536 50000
위의 결과는 50,000 을 short integer 로서 표현하는 bit 패턴이 short 에 의해 -15,536 으로 해석되기 때문이다.
Type Qualifier in C++
Type qualifier 는 변수 앞에서 부가적인 정보를 제공한다.
Qualifier | Meaning |
const | const type 의 개체는 프로그램 실행 동안에 변경될 수 없다. |
volatile | volatile 은 컴파일러에게 변수의 값이 프로그램에 의해서 명시적으로 지정되지 않은 방식으로 변경될 수 있음을 통보한다. |
restrict | restrict 에 의한 pointer qualifier 는 초기에 단지 그것이 가리키는 개체에 의해서만 접근 가능하다는 것을 의미한다. C99 에서만 restrict 라 불리는 새로운 유형의 qualifiler 가 추가되었다. |
volatile 과 restrict 는 정말 잘 안 쓰이는 keyword 이다. 자세한 내용은 다음 링크들을 참조하기 바란다.
[ C/C++ ] volatile 선언의 의미에 대한 정리.
[ 번역 ] Universal CRT 소개 (0) | 2015.12.28 |
---|---|
[ 번역 ] Function Call Operator () (0) | 2012.12.24 |
[ 번역 ] explicit( C++ ) (0) | 2012.12.24 |
[ 번역 ] Template Specialization and Partial Template Specialization (0) | 2012.11.02 |
[ 번역 ] C++ Metadata - Part 1, Singletons and Lookup (0) | 2012.10.31 |
주의 : 공부하면서 정리한 내용이므로 오류가 있을 수 있습니다.
실습 과제 2-6* :
처음에는 Boost 형식 특질 라이브러리가 제공하는 형식 산술이 완벽해 보이겠지만, 사실은 그렇지 않다. 그 라이브러리의 수단들이 포괄하지 않은 형식 범주들과 관계들, 변환들이 적어도 몇 개는 존재한다. 예를 들어, 그 라이브러리는 부호 있는 정수 형식에 대한 부호 없는 버전의 정수 형식을 얻을 수 있는 수단을 제공하지 않는다. 그런 빠진 부분들을 최대한 많이 찾아 볼 것. 각 특질 범주마다 적어도 하나는 있으며, 전체적으로 적어도 11 개는 있다. 빠진 특질들 각각의 인터페이스를 설계하고, 그런 특질이 필요함을 보여 주는 용례도 제시하라.
풀이 :
일단 이 문제를 풀기 위해서는 "형식 산술" 이 의미하는 바에 대해서 이해할 필요가 있다. 책에서는 "형식 산술" 을 다음과 같이 정의하고 있다.
[ 표 2.5 ] 에 나와 있는 메타 함수들은 근본적인 형식 계산들을 수행하는 메타 함수들이다. 지금까지 살펴 본 다른 형식 특질 메타 함수들과는 달리, 이들은 부울 값이 아니라 형식을 계산 결과로 낸다. 이들을 "형식 산술" 의 연산자들이라고 생각하면 될 것이다.
- C++ Template Metaprogramming, 2.7 메타함수의 정의, 48 페이지.
형식 산술을 위한 메타 함수의 리스트는 다음과 같다.
위의 형식 산술 연산자들은 modifier 나 qualifier 를 붙였다가 떼는 역할을 수행하고 있다. 일단 modifier 와 qualifier 의 개념에 대해서 알고 있어야 어떤 것이 가능하고 어떤 것이 불가능한지 판단할 수 있을 것이다. 다음 링크를 참조하라 : [ 번역 ]C++ Modifier Types.
위의 boost 메타 함수들은 modifier 와 관련한 형식 산술 연산자를 제공하고 있지 않다는 것을 알 수 있다.
1. add_unsigned< T >
unsigned modifier 를 추가한다.
용례 :
이것을 직접 구현하려고 했을 때 일반적인 template 구현으로는 구현이 불가했다. 다음과 같은 template 은 에러를 발생시킨다.
const 같은 qualifier 는 "const T" 와 같은 부분 특수화가 가능했지만, 일반적인 modifier 는 그것이 불가능했다. 아마도 modifier 들은 정수형의 기본형에 대해서만 성립하는 것이기 때문에 그런 것이 아닌가 싶다. 예를 들어 unsigned std::vector 같은 표현은 성립하지 않는다. 혹은 [ 번역 ]C++ Modifier Types 에서도 언급하고 있듯이 unsigned 자체가 단축표기로 하나의 형을 나타내기 때문이 아닌가 싶다. 이 경우에는 add_unsigned< unsigned int + T > 의 형태가 되는게 아닌가 싶다.
어쨌든 이를 구현하기 위해서는 다음과 같이 모든 기본형에 대해서 부분 특수화를 하는 수밖에 없다. 아래는 int 에 대해서 부분 특수화를 한 예이다.
2. remove_unsigned< T >
unsigned modifier 를 제거한다.
용례 :
3. add_signed< T >
signed modifier 를 추가한다.
4. remove_signed< T >
singed modifier 를 제거한다.
5. add_long< T >
long modifier 를 추가한다.
6. remove_long< T >
long modifier 를 제거한다.
7. add_short< T >
short modifier 를 추가한다.
8. remove_short< T >
short modifier 를 제거한다.
[ 번역 ] How Do Those Funky Placeholders Work? (0) | 2013.01.03 |
---|---|
C++ Template Metaprogramming 실습 과제 4-5 풀이 (0) | 2012.12.28 |
C++ Template Metaprogramming 실습 과제 4-4 풀이 (0) | 2012.12.17 |
C++ Template Metaprogramming 실습 과제 4-3 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-2 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-1 풀이 (0) | 2012.12.12 |
C++ Template MetaProgramming 실습 과제 4-0 풀이 (0) | 2012.12.10 |
C++ Template MetaProgramming 실습 과제 3-7 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-6 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-5 풀이 (0) | 2012.11.29 |
2013 년부터는 프로그래밍 말고 다른 취미도 가져 보리라고 결심했다. 갑자기 그런 생각이 들었다. 왠지 인생이 우울하다는 ㅠㅠ
그래서 큰 맘 먹고 귀차니즘을 견디고 분당까지 가서 그림을 그리기 위한 도구를 사왔다.
소묘 초급 동영상 강좌도 신청해서 따라해 봤는데 잘 안 된다. ㅎㅎ.
팔이 엄청 아프고 아주 간단해 보이는 것도 잘 안 되서 취미생활임에도 불구하고 스트레스가 ㅡㅡ;;
정말 창작의 고통이 육체적으로 온다.
앞으로 좋은 결과물이 나오면 보상받을 수 있겠지...
주의 : 공부하면서 정리한 것이기 때문에 오류가 있을 수 있습니다.
실습 과제 4-5 :
다음 함수 템플릿은 std::find 에 대한 "컨테이너 기반" ( 반복자 기반이 아니라 ) 인터페이스를 제공하기 위한 것이다.
현재 코드에서, container_find 는 const 컨테이너들에 대해서는 동작하지 않는다. 코드는 std::find 가 돌려 주는 const_iterator 를 Container::iterator 로 변환하려 하는데, 임의의 컨테이너 형식 x 에 대해 Container 는 const x 가 되기 때문에 컴파일이 실패한다. 이 문제를, container_find 의 반환 형식을 계산하는 작은 메타프로그램을 작성하여 해결하라.
풀이 :
이 코드를 보고 "Container& 인데 왠 const 컨테이너가 들어 온다는 거지?" 라는 의문을 가질 수 있다. 하지만 저건 그냥 type 이 아니라 template 매개 변수라는 것에 주목해야 한다. Container 자체에 예를 들면 const vector< int > 로 선언된 것이 들어 올 수 있다.
일단 에러가 나는 상황을 재현해 보자.
이 문제를 해결하는 것은 간단하다. 다음과 같은 메타 함수를 하나 만들어서 반환값이 들어갈 부분에 넣어 주면 된다. 의미를 이해하는 것은 크게 어렵지 않을 것이다.
여기에서 특이한 것은 mpl::identity 를 사용한다는 것이다. mpl::eval_if 는 말 그대로 메타 함수를 평가하는 것이기 때문에 mpl::identity 를 사용하지 않으면 그냥 return 값이 make_iterator< Container > 가 되어 버린다. make_iterator 를 메타 함수로서 실행해 주기 위해서는 mpl::identity 를 상속한 형태가 되어야 하며, 최종적으로는 make_iterator< Container >::type 을 실행함으로써 Container::const_iterator 나 Container::iterator 가 반환된다. make_iterator 가 결국은 mpl::identity 를 상속하게 되기 때문에 mpl::identity::type 을 실행한 것과 동일한 효과를 내는 것이다.
이해를 돕기 위해서 mpl::eval_if 가 실행되고 나서의 결과를 단순하게 표현한다면 다음과 같다.
전체 코드는 다음과 같다.
다른 사람의 구현도 살펴 봤는데 필자와 다르지 않았다.
http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?CPPTM_Answers_-_Exercise_4-5
[ 번역 ] How Do Those Funky Placeholders Work? (0) | 2013.01.03 |
---|---|
C++ Template Metaprogramming 실습 과제 2-6 풀이 (0) | 2012.12.31 |
C++ Template Metaprogramming 실습 과제 4-4 풀이 (0) | 2012.12.17 |
C++ Template Metaprogramming 실습 과제 4-3 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-2 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-1 풀이 (0) | 2012.12.12 |
C++ Template MetaProgramming 실습 과제 4-0 풀이 (0) | 2012.12.10 |
C++ Template MetaProgramming 실습 과제 3-7 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-6 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-5 풀이 (0) | 2012.11.29 |
원문 : C++ Operator Overloading Tutorial, Function Call Operator ()
주의 : 번역이 개판이므로 이상하면 원문을 참조하세요.
주의 : 허락받고 번역한 것이 아니므로 언제든 내려갈 수 있습니다.
주의 : 가독성을 높이기 위해서 잘 알려진 용어나 발음이 비슷한 용어는 한글로 표기합니다.
Function Call Operator ()
C++ 에서 함수 호출 연산자는 () 연산자이다. 이것은 한 가지 중요한 차이점을 제외하고는 이전에 설명한 subscript 연산자( 역주 : [] )와 유사하게 중복정의된다( overloaded ). subscript 연산자는 단지 하나의 인자만을 받는 반면에, 함수 호출 연산자는 다양한 형식의 여러 인자들을 받을 수 있다. 이러한 특별한 사실은 우리에게 매우 중요하다.
예를 들어 우리가 2 차원 배열 클래스를 가지고 있다면 우리는 배열의 특정 cell 을 참조하기 위해서 [] 를 중복정의할 수 없다. 왜냐하면 [] 는 인자로 하나의 값만을 취하기 때문이다. 그러나 우리는 () 연산자를 중복정의할 수 있다. 왜냐하면 그것은 다중의 인자들을 취할 수 있으며, 즉 우리는 인자로 row 와 column 을 지정할 수 있다. 사실 그 함수 호출 연산자는 단지 다양한 형식의 가변 개수의 인자들을 취할 수 있는 중복정의된 연산자일 뿐이다. 이는 우리가 다양한 상황에서 그것을 사용( 혹은 잘 못 사용)할 수 있게 해 준다.
우리의 예제를 위해, 우리는 () 연산자가 [] 연산자와 동일한 일을 수행하도록 중복정의하고 이전 예제를 빌드할 것이다. 공교롭게도 어떤 언어들( BASIC 이나 FORTRAN )은 () 를 배열 subscripting 을 위해 사용한다. 그래서 사람들은 그러한 방식으로 사용되는 () 을 보는데 익숙하다. 우리는 클래스에 다른 멤버 함수를 추가함으로써 작업을 시작한다.
이 함수 구현은 이전 페이지의 것과 매우 유사하다.
이전처럼 우리는 이 개체를 다음과 같이 검사할 수 있다 :
이 코드를 실행하면 원하는 결과를 산출한다.
이전 페이지( subscript operator )에서 보았듯이, 항상 참조를 반환할 필요는 없다. 예를 들어 당신이 개체를 읽기 전용으로 만들기 원한다면, int& 참조 대신에 const int 를 반환하도록 만들 수 있다.
Excercises
1. 우리의 중복 정의된 연산자는 배열 범위 내에 index 가 있는지 검사하지 않는다. 필요하면 예외를 던지도록 코드를 추가하라. 예외를 던지는 대신에 필요하면 배열 크기를 변경할 수 있는 다른 버전도 만들어 보라.
2. 컴파일러에 의해 생성되는 기본 복사 생성자는 문제가 있다. 그것은 개체의 인스턴스로부터 다른 인스턴스로 데이터를 복사하는 대신에 포인터를 복사한다. 두 개의 포인터가 같은 메모리를 가지고 있기 때문에 하나가 파괴가 될 때 문제가 발생한다. 다른 인스턴스의 포인터는 해제된 메모리를 가리키게 된다. 해결책은 자신만의 복사 생성자를 작성해서 적절하게 데이터의 복사본을 만드는 것이다. 적절하게 데이터를 다루기 위한 복사 생성자를 작성하라.
3. 2 차원 배열을 다루기 위해 클래스를 재작성하라. 다음 코드는 당신이 작업을 시작하는데 도움을 줄 것이다.
아래 코드로 검증하라.
[ 번역 ] Universal CRT 소개 (0) | 2015.12.28 |
---|---|
[ 번역 ] C++ Modifier Types (0) | 2013.01.02 |
[ 번역 ] explicit( C++ ) (0) | 2012.12.24 |
[ 번역 ] Template Specialization and Partial Template Specialization (0) | 2012.11.02 |
[ 번역 ] C++ Metadata - Part 1, Singletons and Lookup (0) | 2012.10.31 |
출처 : MSDN, explicit( C++ )
주의 : 번역이 개판이므로 원문을 참조하세요.
주의 : 가독성을 높이기 위해, 잘 알려진 용어나 발음이 비슷한 용어는 한글로 표기합니다.
주의 : 허락받고 번역한 것이 아니므로 언제든 내려갈 수 있습니다.
explicit ( C++ )
하나의 매개변수만을 가지는 C++ 생성자는 자동적으로 묵시적( implicit ) 형변환을 수행한다. 예를 들어, 생성자가 문자열 포인터를 기대하고 있을 때 당신이 int 를 넘겨준다면, 컴파일러는 int 를 문자열 포인터로 변환해야만 한다는 코드를 추가할 것이다. 그러나 당신이 이러한 자동적인 행위를 항상 원하는 것은 아닐 것이다.
당신은 생성자 선언에 explicit 를 추가하여 묵시적인 변환을 방지할 수 있다. 이는 그 코드를 올바른 형식의 매개변수를 사용하거나 올바른 형식으로 매개변수를 변환하는 것을 강제한다. 즉 그 변환이 명시적으로( visibly ) 코드에 표현되어 있지 않다면, 에러가 발생할 것이다.
explicit 키워드는 명시적으로 개체를 생성하기 위해서 in-class 생성자 선언에만 적용될 수 있다.
Example
다음 프로그램을 컴파일하는 것은 에러를 산출한다. 이 코드는 묵시적 형변환을 수행하려고 하지만, explicit 키워드의 사용이 그것을 방지한다. 이 에러를 해결하기 위해서는 explicit 키워드를 제거하고 g 의 코드를 적용하라.
[ 번역 ] Universal CRT 소개 (0) | 2015.12.28 |
---|---|
[ 번역 ] C++ Modifier Types (0) | 2013.01.02 |
[ 번역 ] Function Call Operator () (0) | 2012.12.24 |
[ 번역 ] Template Specialization and Partial Template Specialization (0) | 2012.11.02 |
[ 번역 ] C++ Metadata - Part 1, Singletons and Lookup (0) | 2012.10.31 |
주의 : 공부하면서 정리한 것이기 때문에 오류가 있을 수 있습니다.
실습 과제 4-4 :
정수 연산자들과 형식 특질 라이브러리의 수단을 이용해서 다음의 합성 특질들을 구현하라.
is_data_member_pointer
is_pointer_to_function
is_reference_to_function_pointer
is_reference_to_non_const
풀이 :
이 문제는 논리 연산자들을 적절하게 사용해 메타 함수를 합성하는 방법을 알고 있는지 확인하는 문제이다.
일단 함수를 합성하기 위해서는 문제에 나온 함수를 각각의 ( 함수 ) 요소로 분해할 수 있어야 한다.
1. is_data_member_pointer
이 메타 함수는 다음과 같이 분해된다.
is_data_member_pointer = is_member_pointer && !( is_member_function_pointer )
그리고 나서 이 함수를 테스트하는데 사용할 class 를 정의해 보자.
그런데 여기에서 문제가 발생한다. 우리가 만든 메타 함수는 매개변수로 type 을 받아 들이므로 우리가 테스트하고 싶어하는 field 의 형식에 어떻게 접근해야 할지 알 수 없다는 것이다. 예를 들어 다음과 같이 테스트하는 것은 오류이다.
그래서 C++ 0x 부터 추가된 decltype 을 사용해 봤다. 그런데 다음과 같은 결과가 나온다.
결국 어떻게 테스트해야 하는지 알수 없어서 CPPTM Answers - Exercise 4-4 를 참조했다. 여기에서는 빈 클래스인 foo 를 선언하고, typedef 를 통해서 새로운 type 을 선언했다. 일단은 그렇게 테스트를 해 봤다.
나중에 member variable 에서 class 까지 포함하는 type 을 획득할 수 있는 방법에 대해서 알아 봐야 겠다.
2. is_pointer_to_function
이 문제는 함수 포인터의 본질에 대해서 얼마나 이해하고 있느냐를 확인하고 있다. 처음에는 다음과 같이 생각했다.
is_pointer_to_function = is_function || is_member_function_pointer
그런데 "왜 is_function 은 is_function_pointer 가 아닌 것일까?" 라는 의문이 들기 시작했고, 다른 사람의 구현을 살펴 보았다.
http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?CPPTM_Answers_-_Exercise_4-4
사실 함수포인터는 그냥 함수라고 생각했었는데, 지금까지 아주 잘못된 생각을 하고 있다는 것을 알았다. 일반적인 변수와 유사하게 함수 자체도 변수처럼 동작하는 것이었다. 그래서 여기에서 함수 포인터에 대해 다시 짚어 볼 필요가 있었다. 다음은 함수 포인터의 예이다. 다음 링크에서 가지고 온 예이다 : Program as Data: Function Pointers
위의 예에서 마치 변수의 주소를 구하듯이 함수의 주소를 구하는 것을 볼 수 있다. 변수는 어떤 메모리 공간에 대한 이름이다. 그리고 그 이름은 어떠한 주소로 매핑된다. 위에서도 언급했듯이 변수와 마찬가지로 함수는 어떤 로직을 담고 있는 메모리 공간에 대한 이름이 되겠다. 그러므로 이것도 참조하거나 포인팅하는 것이 가능한 것이다. 특이한 점은 그 포인터 자체에 () 연산자를 걸어서 호출이 가능하다는 것이다. () 연산자에 대해서는 다음 글을 참조하기 바란다 : [ 번역 ] Function Call Operator ().
그런데 위의 구현은 한 가지 문제가 있다. mpl::and_ 의 두 번째 매개 변수에서 ::type 을 지정함으로써 지연 평가가 이루어지지 않는다는 것이다. 이를 지연 평가가 가능하게 고쳐 보려고 했는데 잘 되지 않았다. 이 부분도 연구해 볼 필요가 있다.
어쨌든 is_pointer_to_function 은 다음과 같은 표현이라고 할 수 있다.
is_pointer_to_function = is_pointer && ( is_function( remove_pointer ) )
그리고 위의 구현은 불필요하게 and_ 를 호출하고 있기 때문에 최종적으로는 다음과 같이 구현할 수 있다.
3. is_reference_to_function_pointer
점점 복잡해 지고 있다. 하지만 function 에 대해서 이해한 상황이기 때문에 그리 어려울 것은 없다. 앞에서 만들었던 is_pointer_to_function 을 재사용하고, boost::remove_reference 로 reference 를 제거해 주기만 하면 된다.
is_reference_to_function_pointer = is_reference && ( is_pointer_to_function( remove_reference ) )
코드는 다음과 같다.
4. is_reference_to_non_const
이 문제는 비교적 쉬운데 다음과 같이 표현할 수 있다.
is_reference_to_non_const = is_reference && !( is_const( remove_reference ) )
코드는 다음과 같다.
여기에서 의문을 가지는 사람이 있을 것이다. 왜 is_const 에서 remove_reference 를 해야 하는 것일까? 필자가 다음과 같이 test 했을 때 error 를 냈다.
아직까지 그 이유는 정확하게 모르겠지만 추측해 보면, boost 의 type traits 는 특정 순서대로 한정자를 제거해 가면서 type check 를 하도록 만들어져 있는 것 같다.
[ 번역 ] How Do Those Funky Placeholders Work? (0) | 2013.01.03 |
---|---|
C++ Template Metaprogramming 실습 과제 2-6 풀이 (0) | 2012.12.31 |
C++ Template Metaprogramming 실습 과제 4-5 풀이 (0) | 2012.12.28 |
C++ Template Metaprogramming 실습 과제 4-3 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-2 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-1 풀이 (0) | 2012.12.12 |
C++ Template MetaProgramming 실습 과제 4-0 풀이 (0) | 2012.12.10 |
C++ Template MetaProgramming 실습 과제 3-7 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-6 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-5 풀이 (0) | 2012.11.29 |
주의 : 공부하면서 정리한 것이기 때문에 오류가 있을 수 있습니다.
실습 과제 4-3 :
다음 코드에서 불필요한 인스턴스화를 제거하라.
수정된 메타함수들의 의미론이 수정되기 전과 동일한지를 점검하는 테스트들도 작성하라.
풀이 :
위의 문제들은 게으른 평가에 대한 이해도를 확인하는 문제이다. ::type 이나 ::value 가 불리는 순간 해당 템플릿은 인스턴스화된다. 그러므로 게으른 평가를 위해서는 메타함수들이 실제로 평가되지 않도록 ::type 이나 ::value 를 없애야만 한다. 물론 반드시 필요한데 호출하는 코드를 지워버린다면 에러가 나므로 주의해야 한다.
1. next_if 메타 함수.
일단 next_if 의 의미를 파악하자.
N 을 Predicate 함수에 적용한 결과가 true 이면
mpl::next< N > 을 호출한 결과를 반환하고
그렇지 않으면
N 을 그대로 반환한다.
mpl::next 는 다음과 같은 기능을 가지고 있다.
순차열 안의 다음 반복자( iterator )를 반환한다. [ 주의 : next 는 여러 개의 중복된 의미를 가지는데, 그것의 인자의 형식에 따라 다르다. 예를 들어 X 가 정수형 상수라면, next< X > 는 같은 형식의 증가된 정수형 상수를 반환한다. 이후의 명세는 iterator-specific 하다. 대안으로 선택할 수 있는 구문에 대한 세부적인 설명을 원한다면 관련 개념들의 문서를 참조하기 바란다. ]
- http://www.boost.org/doc/libs/1_52_0/libs/mpl/doc/refmanual/next.html
'predicate' 는 '술어' 라는 뜻이기 때문에 mpl::if_ 의 조건을 결정하기 위한 서술문을 의미하는 메타 함수를 의미한다고 보면 될 것이다. 예를 들어 C++ 식으로 표현하면 다음과 같다; if( true == Predicate( N ) ){ ... }.
이를 테스트하기 위해서는 Predicate 를 평가해서 나온 ::type 이 가리키는 형식이 반드시 ::value 라는 멤버를 가지고 있어야만 한다. 그래서 다음과 같은 식으로 평가를 해 볼 수 있다. Predicate 의 형태를 보요 주기 위해서 메타 함수 클래스를 사용한 경우와 자리표 표현식을 사용한 경우의 두 가지 예제를 모두 보여 주겠다.
자 이제 이것을 게으른 평가가되도록 최적화해 보자.
현재 mpl::apply 메타 함수의 ::type 과 mpl::next 메타 함수의 ::type 이 불리고 있다. 책에서 배운 대로 mpl::identity 를 사용해서 제거해 보도록 하자.
안타깝게도 우리의 기대를 무참하게 짓밟아 버린다. 왜일까?
mpl::identity::type 은 그것의 매개변수로 들어 왔던 스칼라나 메타함수의 원형을 그대로 돌려 준다. 그러므로 아직까지는 mpl::identity< mpl::next< N > > 과 mpl::next< N > 이 평가되지 않은 상황이다. 이를 해결하기 위해서는 next_if2 : mpl::if_< ... >::type 으로 만들어 주거나 사용할 때 next_if2< ... >::type::type::value 를 통해 값을 가져와야 한다. 사용자들은 보통 ::type 을 한 번만 사용한다고 인지하고 있기 때문에 필자는 구조체 쪽에서 처리하는 방법을 택했다. 최종 코드는 아래와 같다.
사실 mpl::eval_if 를 사용하면 mpl::identity 를 사용할 필요가 없다. 물론 다들 알고 있겠지만 책에서 배운 내용을 점검해 보는 차원에서 위의 방식으로 풀어 보았다. 실제로 아래와 같이 매우 깔끔한 코드를 만들 수 있다.
2. formula 메타 함수.
mpl::not_equal_to 는 integral constant 에 대해서 적용되므로 N1 과 N2 가 integral constant 라는 것을 알 수 있다. 그러므로 formula 메타 함수는 다음과 같은 기능을 가지고 있다.
IF N1 과 N2 가 다르면
IF N1 이 N2 보다 크면
N1 에서 N2 를 뺀 결과 반환.
ELSE
N1 을 반환.
ELSE
N1 에 N1 에다 2를 더한 결과를 더한 결과 반환.
조금 복잡하기는 하지만 1 번과 크게 다를 것 없다. 일단 mpl::if_ 를 mpl::eval_if 로 바꾼다. 그리고 나서 mpl::eval_if 내의 메타 함수들에서 불필요한 ::type 을 제거한다.
[ 번역 ] How Do Those Funky Placeholders Work? (0) | 2013.01.03 |
---|---|
C++ Template Metaprogramming 실습 과제 2-6 풀이 (0) | 2012.12.31 |
C++ Template Metaprogramming 실습 과제 4-5 풀이 (0) | 2012.12.28 |
C++ Template Metaprogramming 실습 과제 4-4 풀이 (0) | 2012.12.17 |
C++ Template Metaprogramming 실습 과제 4-2 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-1 풀이 (0) | 2012.12.12 |
C++ Template MetaProgramming 실습 과제 4-0 풀이 (0) | 2012.12.10 |
C++ Template MetaProgramming 실습 과제 3-7 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-6 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-5 풀이 (0) | 2012.11.29 |
주의 : 공부하면서 정리한 내용이므로 오류가 있을 수 있습니다.
실습 과제 4-2 :
실습 과제 4-1 의 logical_or 와 logical_and 메타 함수들의 구현을, 인수들을 최대 5 개까지 받을 수 있도록 확장하라.
풀이 :
이 문제를 해결하기 위해서는 가변 개수의 매개변수들을 받을 수 있는 구조를 만들어야 한다.
하지만 안타깝게도 템플릿에 가변 개수의 매개변수를 받을 수 있는 방법은 없다. 일단은 5 개의 매개변수를 받을 수 있는 logical_or 와 logical_and 를 만드는 데서부터 시작하자.
그런데 ( 2 개 이상인 ) 가변 개수의 매개변수를 받기 위해서는 어떻게 해야 할까? 이를 위해서는 템플릿 매개변수에 initializer 를 설정하는 방법이 있다. 사용자가 매개변수를 입력하지 않더라도 자동으로 기본값이 들어 가도록 하는 방법이다. none_ 이라는 구조체를 기본값으로 설정하고, 만약 그 구조체가 입력되면 연산을 종료한다고 가정했다.
이제 logical_and_impl 구현해야 하는데, 이것을 인자가 5 개인 것부터 2 개인 것까지 구현을 한다. 그리고 logical_and_impl 가 다음 매개변수들을 위해 실행되어야 할지를 판단하기 위해 mpl::eval_if 를 사용한다. 다음 매개변수들을 위해 실행되지 않는 경우는 두 가지이다; 현재 조건이 false 일 경우와 매개변수가 none_ 일 경우이다.
매개변수가 none_ 일 경우를 위해서 부분특수화를 구현했다. 그리고 mpl::eval_if 는 게으른 평가를 수행하므로 4-1 의 문제가 제시한 조건을 만족한다.
다음은 소스 코드이다. 그런데 logical_or 는 귀차니즘 때문에 구현하지 않았다. 비슷한 방식으로 구현하면 된다.
다른 사람의 구현도 살펴 보자.
http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?CPPTM_Answers_-_Exercise_4-2
[ 번역 ] How Do Those Funky Placeholders Work? (0) | 2013.01.03 |
---|---|
C++ Template Metaprogramming 실습 과제 2-6 풀이 (0) | 2012.12.31 |
C++ Template Metaprogramming 실습 과제 4-5 풀이 (0) | 2012.12.28 |
C++ Template Metaprogramming 실습 과제 4-4 풀이 (0) | 2012.12.17 |
C++ Template Metaprogramming 실습 과제 4-3 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-1 풀이 (0) | 2012.12.12 |
C++ Template MetaProgramming 실습 과제 4-0 풀이 (0) | 2012.12.10 |
C++ Template MetaProgramming 실습 과제 3-7 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-6 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-5 풀이 (0) | 2012.11.29 |
주의 : 공부하면서 정리한 내용이므로 오류가 있을 수 있습니다.
실습 과제 4-1 :
mpl::or_ 와 mpl::and_ 를 본 딴, logical_or 와 logical_and 라는 이름의 이항 메타함수들을 구현하라. 그리고 실습 과제 4-0 의 테스트들로 그 구현을 시험하라.
풀이 :
이 문제는 게으른 평가( lazy evaluation )에 대한 이해를 얼마나 하고 있는지를 확인하는 문제이다. 게으른 평가가 되기 위해서는 ::type 이나 ::value 가 명시적으로 지정되면 안 된다.
필자는 부분 특수화를 통해서 이 문제를 해결했다. 자세한 사항은 주석을 참조하라.
아래 링크에 있는 다른 사람의 구현도 살펴 보기 바란다.
http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?CPPTM_Answers_-_Exercise_4-1
C++ Template Metaprogramming 실습 과제 2-6 풀이 (0) | 2012.12.31 |
---|---|
C++ Template Metaprogramming 실습 과제 4-5 풀이 (0) | 2012.12.28 |
C++ Template Metaprogramming 실습 과제 4-4 풀이 (0) | 2012.12.17 |
C++ Template Metaprogramming 실습 과제 4-3 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-2 풀이 (0) | 2012.12.13 |
C++ Template MetaProgramming 실습 과제 4-0 풀이 (0) | 2012.12.10 |
C++ Template MetaProgramming 실습 과제 3-7 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-6 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-5 풀이 (0) | 2012.11.29 |
C++ Template MetaProgramming 실습 과제 3-4 풀이 보충 (0) | 2012.11.28 |
주의 : 공부하면서 정리하는 것이기 때문에 오류가 있을 수 있습니다.
실습 과제 4-0 :
mpl::or_ 와 mpl::and_ 메타 함수에 대해, 부울 표현식의 평가 단축 행동을 시험하는 테스트를 작성하라.
풀이 :
이 문제는 "평가 단축 행동"의 의미를 이해하고 있는지를 묻고 있다. 책에서는 다음과 같이 표현하고 있다.
내장 연산자 &&, || 과 마찬가지로, mpl::and_ 와 mpl::or_ 는 "평가 단축" 행동을 가진다는 점 역시 알아둘 필요가 있을 것이다.
- C++ Template Metaprogramming, 4.2 정수 래퍼들과 연산들, 91 페이지.
"평가 단축" 이라고 하는 것은 앞의 결과가 false 면 뒤의 결과를 평가하지 않는다는 것이다. 예를 들어 "A && B" 는 둘 다 true 일 때만 true 이므로 && 연산자의 앞의 피연산자인 A 가 false 이면 B 는 볼 필요도 없이 && 의 결과는 false 이다. 이를 통해 평가 비용을 단축할 수 있다.
이를 테스트해 보기 위해서는 bool 을 반환하는 두 개의 메타 함수가 필요하다. 책에서 많이 나오고 있는 boost::is_scalar 를 첫 번째 메타 함수로 만들고, 항상 컴파일 에러를 내는 Error 라는 메타 함수를 만들자. 그리고 나서 mpl::or_ 와 mpl::and_ 의 두 번째 매개변수로 넣는다.
C++ Template Metaprogramming 실습 과제 4-5 풀이 (0) | 2012.12.28 |
---|---|
C++ Template Metaprogramming 실습 과제 4-4 풀이 (0) | 2012.12.17 |
C++ Template Metaprogramming 실습 과제 4-3 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-2 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-1 풀이 (0) | 2012.12.12 |
C++ Template MetaProgramming 실습 과제 3-7 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-6 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-5 풀이 (0) | 2012.11.29 |
C++ Template MetaProgramming 실습 과제 3-4 풀이 보충 (0) | 2012.11.28 |
[ 번역 ] CPPTM Answers - Exercise 3-4 (0) | 2012.11.28 |
주의 : 공부하면서 정리한 내용이기 때문에 오류가 있을 수 있습니다.
실습 과제 3-7* :
다음 구성물들의 의미론은 무엇일까?
독자의 답에 도달한 단계들을 보이고, 독자의 가정들을 확인하는 테스트 코드를 작성하라. 라이브러리의 행동이 독자의 분석과 일치하는가? 그렇지 않다면, 실패한 테스트들을 분석해서 실제의 표현식들의 의미론을 파악해 볼 것. 그리고 독자의 가정들이 왜 달랐는지, 또 독자가 생각하기에 어떤 행동이 더 합당한지와 그 이유를 말해 보라.
풀이 :
이 역시 쉬운 듯하면서 절대 쉽지 않은 문제이다. 지금까지 배웠던 람다 표현식에 대해서 얼마나 이해하고 있는지를 검사하는 문제이다. 게다가 근거까지 명확하게 대야 하기 때문에 별표가 안 붙을 수 없다.
typedef mpl::lambda< mpl::lambda< _1 > >::type t1;
mpl::lambda 메타 함수는 자리표 표현식을 위한 메타 함수 클래스를 만들어 내는 역할을 하고 있다고 알고 있었다. 그리고 결국에는 메타 함수 자체를 반환한다고 생각했다.
_1 은 arg< 1 > 이라는 메타 함수 클래스이고 _1 로 평가되기 때문에 첫 번째 lambda 에서 _1 을 반환하고, 두 번째 lambda 에서 다시 _1 을 반환해 t1 은 _1 을 반환한다고 생각했다. 그래서 예상한 결과는 다음과 같았다.
그러나 이는 전혀 평가되지 않는 문장을 만들어 냈다. 아래 에러와 같이 그냥 문자열처럼 해석해 버린다.
error C2338: ( boost::is_same< t1::type, _1 >::value )
생각해 보니 t1 이라는 것 자체가 어떤 메타 함수 클래스를 나타내기는 하지만, 실제로 어떤 형식을 넣어 특수화하지 않으면 아무런 의미도 없겠다는 생각이 들었다. 그래서 다음과 같이 고쳐 봤다. 자리표 표현식으로부터 메타 함수 클래스를 생성해 주는 것이기 때문에 apply 를 호출해 보았다.
위의 코드 역시 평가되지 않았다.
결국 기본부터 다시 생각해 보기로 했다.
mpl::lambda 의 의미부터 다시 파악해 볼 필요가 있다. mpl::lambda 는 자리표 표현식이나 메타 함수 클래스를 받아서 메타 함수 클래스를 만들어 준다. 만약 boost::add_pointer 라는 메타 함수를 위한 메타 함수 클래스를 만들기 위해서는 다음과 같이 해야 한다.
자 그러면 아무런 메타 함수나 넣어서 호출할 수 있게 해주는 메타 함수를 만들기 위해서는 어떻게 해야 할까? 다음과 같은 형태를 생각할 수 있다.
??? 자리에는 람다 표현식( 자리표 표현식이나 메타 함수 클래스 )이 들어 와야 할 것이다. 메타 함수 자체는 일급 메타 자료가 아니기 때문이다. 그런데 공급될 것이 메타 함수인지 람다 표현식인지 알 수 없기 때문에, 모든 가능성을 생각하면 무엇이 들어 오든 람다 표현식으로 만들어 줄 필요가 있다. 그러므로 다음과 같이 표현할 수 있다.
위 코드는 메타 함수나 람다 표현식을 메타 함수 클래스로 만들어 주는 메타 함수 클래스를 정의한 것이라고 할 수 있다. 이를 실제로 사용해 보도록 하겠다.
typedef mpl::apply< _1, mpl::plus< _1, _2 > >::type t2;
이것은 mpl::apply 에 의해 내부의 mpl::plus 를 평가한 결과를 외부의 mpl::apply 에 적용하는 메타 함수로 보인다. 일반적으로 mpl::plus 에 들어 오는 것은 수치 래퍼일 것이기 때문에 그것의 ::type 은 자기 자신을 반환할 것이다. 결국 이는 mpl::plus 와 동일한 결과를 낼 것이다.
one 과 two 를 mpl::plus 의 _1 과 _2 에 할당하고 나면 mpl::int_< 3 > 이라는 결과가 나올 것이고, 그것이 다시 mpl::apply 의 _1 에 들어 가서 그것을 평가하면 그 자신을 반환한다.
typedef mpl::apply< _1, std::vector< int > >::type t3;
일단 std::vector 가 메타 함수인지를 확인해 봐야 한다. 그런데 std::vector 는 type 이라는 내포된 형식을 가지고 있지 않았다. 그걸 봤을 때 메타 함수는 아니라고 생각했으며, 이를 인스턴스화하면 에러가 날 것이라 생각했다.
하지만 실제로 해 봤을 때 다음과 같은 코드가 유효했다.
그런데 책에 이미 내용이 나와 있었다.
자리표에 대해 아직 이야기하지 않은 세부사항이 하나 있다. MPL 은 보통의 템플릿들을 메타 프로그램에 통합시키기 쉽게 만들기 위한 하나의 특별한 규칙을 사용한다. 어떤 규칙이냐 하면, 모든 자리표들이 실제 인수들로 치환된 후의 템플릿 특수화 X 에 내포된 ::type 이 존재하지 않는다면, 그 람다의 결과는 X 자체라는 것이다.
- C++ Template MetaProgramming, 3.5.3 람다와 비 메타함수 템플릿, 77 페이지.
역시 책만 읽고 "아 그렇구나" 하고 넘어가면 안 된다는 점을 다시 한 번 느끼게 됐다.
typedef mpl::apply< _1, std::vector< _1 > >::type t4;
이것은 어떤 형식을 받아 vector 를 만들어 주는 메타 함수이다.
typedef mpl::apply< mpl::lambda< _1 >, std::vector< int > >::type t5;
std::vector< int > 을 입력으로 mpl::lambda< _1 > 가 지정하는 메타함수를 실행해 주는 메타함수라고 생각했다. 하지만 실제 해 보니 t5 에는 apply 라는 메타 함수가 존재하지 않고 그냥 std::vector< int > 와 같았다.
좀 이해할 수 없는 결과였다. 그런데 가만히 생각해 보니, 내부에 있는 mpl::lambda< _1 > 이라는 것이 평가되면 그냥 _1 이 되기 때문에 결국에는 t3 와 같은 결과가 되는 것이었다.
typedef mpl::apply< mpl::lambda< _1 >, std::vector< _1 > >::type t6;
이것 역시 내부의 mpl::lambda< _1 > 이 _1 로 평가되면서 t4 와 같은 결과를 낸다.
typedef mpl::apply< mpl::lambda< _1 >, mpl::plus< _1, _2 > >::type t7;
이것 역시 내부의 mpl::lambda< _1 > 이 _1 로 평가되면서 t2 와 같은 결과를 낸다.
typedef mpl::apply< _1, mpl::lambda< mpl::plus< _1, _2 > > >::type t8;
mpl::lambda< mpl::plus< _1, _2 > > 는 mpl::plus< _1, _2 > 로 평가되고, 이것은 mpl::apply 의 _1 에 그대로 들어 가기 때문에 최종적으로는 mpl::plus< _1, _2 > 만 남는다.
다른 사람의 해석도 살펴 보기 바란다.
http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?CPPTM_Answers_-_Exercise_3-7
C++ Template Metaprogramming 실습 과제 4-4 풀이 (0) | 2012.12.17 |
---|---|
C++ Template Metaprogramming 실습 과제 4-3 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-2 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-1 풀이 (0) | 2012.12.12 |
C++ Template MetaProgramming 실습 과제 4-0 풀이 (0) | 2012.12.10 |
C++ Template MetaProgramming 실습 과제 3-6 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-5 풀이 (0) | 2012.11.29 |
C++ Template MetaProgramming 실습 과제 3-4 풀이 보충 (0) | 2012.11.28 |
[ 번역 ] CPPTM Answers - Exercise 3-4 (0) | 2012.11.28 |
C++ Template MetaProgramming 실습 과제 3-4 풀이. (0) | 2012.11.26 |
주의 : 공부하면서 정리한 것이므로 오류가 있을 수 있습니다.
실습 과제 3-6 :
twice 와 같은 기능을 가진 람다 표현식을 작성하라. 힌트 : mpl::apply 는 메타함수임.
풀이 :
mpl::apply 메타 함수는 메타함수를 템플릿 매개 변수로 받아 호출해 주는 예제이다. 예를 들어 boost::add_pointer 는 그냥 메타 함수이기 때문에( 일급 메타 자료가 아니기 때문에 ) 다른 메타 함수의 매개변수로 설정될 수 없다. 이를 가능하게 하기 위해서는 람다 표현식을 만들어야 한다.
람다 표현식은 다음과 같다.
람다 표현식( lambda expression ). 간단히 말하면, 람다 표현식은 호출 가능한 메타자료이다. 어떤 형태이든 호출 가능한 메타자료라는 것이 없으면 고차 메타함수는 불가능하다. 람다 표현식은 두 가지 형태인데, 하나는 메타함수 클래스이고 또 하나는 자리표 표현식이다.
- C++ Template MetaProgramming, 3.6 세부사항, 79 페이지.
책에서 메타함수 클래스를 만드는 것과 메타함수 전달을 하는 법에 대해서 설명을 많이 하고 있다. 여기에서 굳이 이 문제를 내는 이유는 비관입적으로 메타함수들을 호출하는 법을 제대로 알고 있는지에 대해서 확인하는게 아닐까 싶다.
필자같은 경우에는 자리표 표현식을 사용해 이를 람다표현식으로 표현해 보았다.
자리표 표현식( placeholder expression ). 람다 표현식의 한 종류로, 자리표들을 이용해서 즉석의 부분적 메타함수 적용과 메타함수 합성을 가능하게 한다. 이 책 전반에서 나오겠지만, 이러한 기능은 필요한 바로 그 자리에서 기초적인 메타함수들로 거의 모든 종류의 좀 더 복잡한 형식 계산을 구성할 수 있게 한다.
- C++ Template MetaProgramming, 3.6 세부사항, 79 페이지.
다른 사람들은 어떻게 구현하고 있는지 살펴 보기 바란다.
http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?CPPTM_Answers_-_Exercise_3-6
C++ Template Metaprogramming 실습 과제 4-3 풀이 (0) | 2012.12.13 |
---|---|
C++ Template Metaprogramming 실습 과제 4-2 풀이 (0) | 2012.12.13 |
C++ Template Metaprogramming 실습 과제 4-1 풀이 (0) | 2012.12.12 |
C++ Template MetaProgramming 실습 과제 4-0 풀이 (0) | 2012.12.10 |
C++ Template MetaProgramming 실습 과제 3-7 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-5 풀이 (0) | 2012.11.29 |
C++ Template MetaProgramming 실습 과제 3-4 풀이 보충 (0) | 2012.11.28 |
[ 번역 ] CPPTM Answers - Exercise 3-4 (0) | 2012.11.28 |
C++ Template MetaProgramming 실습 과제 3-4 풀이. (0) | 2012.11.26 |
C++ Template MetaProgramming 실습 과제 3-3 풀이 (0) | 2012.11.26 |
주의 : 공부하면서 정리한 내용이므로 오류가 있을 수 있습니다.
실습 과제 3-5 :
3.1 절의 차원 해석 코드에는 한 가지 문제가 남아 있다. 힌트 : 다음 코드를 시험해 볼 것.
이 문제를 이번 장에 나온 기법들을 이용해서 고쳐 보라.
풀이 :
m * a 가 만들어 내는 차원 정보는 순차열 내의 값은 동일하지만 같은 형식이라고 할 수 없다. 그러므로 + 연산자와 - 연산자에서 복사 생성자를 만들때 했던 것처럼 형식 검사를 해 줘야 한다.
하는 김에 * 연산자와 / 연산자에서 이 장에 나온 자리표 표현식을 사용해 보았다.
C++ Template Metaprogramming 실습 과제 4-2 풀이 (0) | 2012.12.13 |
---|---|
C++ Template Metaprogramming 실습 과제 4-1 풀이 (0) | 2012.12.12 |
C++ Template MetaProgramming 실습 과제 4-0 풀이 (0) | 2012.12.10 |
C++ Template MetaProgramming 실습 과제 3-7 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-6 풀이 (0) | 2012.12.01 |
C++ Template MetaProgramming 실습 과제 3-4 풀이 보충 (0) | 2012.11.28 |
[ 번역 ] CPPTM Answers - Exercise 3-4 (0) | 2012.11.28 |
C++ Template MetaProgramming 실습 과제 3-4 풀이. (0) | 2012.11.26 |
C++ Template MetaProgramming 실습 과제 3-3 풀이 (0) | 2012.11.26 |
C++ Template MetaProgramming 실습 과제 3-2 풀이 (0) | 2012.11.25 |