SlideShare a Scribd company logo
1 of 129
C++11 features
used in Crow
Crow를 통해 살펴보는 C++11의 새 기능
하재승
@ipkn
ipknhama@gmail.com
Crow Framework을 작성하기 위해
사용한 기법들을 소개 (TMP 중심)
auto, lambda등
일반적인 C++ 개발에서 접하기 쉬운
기법들에 대한 설명은 생략
목표
목표
Crow
C++ Framework for writing Web server
http://github.com/ipkn/crow
GitHub Star 1063개
Hacker News vote 194
https://news.ycombinator.com/item?id=8002604
Web server 개념
브라우저로 접속해서 요청을 보내면
해당 요청에 맞는 응답을 보내줌
GET / HTTP/1.1
Host: www.example.com
HTTP/1.1 200 OK
Content-Length: 12
...
Hello World!
간단한 Crow 예제
#include “crow_all.h”
int main() {
crow::SimpleApp app;
CROW_ROUTE(app, “/”)
([]{
return “Hello world!”;
});
app.port(8080).run();
return 0;
}
… as Flask (from Quickstart)
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
목차
Routing
Compile time
Run time
Middleware
서버 구조
소개될 C++11 기능
template metaprogramming
constexpr
variadic template
SFINAE
decltype, declval
std::chrono, operator ””, enum class
왜 굳이 C++로?
https://github.com/ipkn/crow-benchmark
C++?
빠른 속도
멀티 패러다임 언어
절차형 + OOP + Generic (template)
template
compile time code generation
vector<T> →
vector<int>, vector<string>
T는 컴파일 타임에 결정되어야 한다.
Crow 클래스 구조
App
Server
Connection
Router
Rule (TaggedRule)
Trie
Routing
Routing - CROW_ROUTE
어떤 요청에 어떤 응답을 줄지 지정
CROW_ROUTE(app, “/”)
CROW_ROUTE(app, “/post/all”)
CROW_ROUTE(app, “/post/<int>”)
CROW_ROUTE(app,
“/near/<double>/<double>”)
CROW_ROUTE 목표
쓰기 편하게
실수하기 어렵게
잘못된 핸들러를 주면 에러나게
빠르게
실제 함수 호출 시 오버헤드를 최소화
CROW_ROUTE 기능 (1)
여러 타입의 인자 지원
<int>
<uint>
<double>
<str>
<path>
CROW_ROUTE 기능 (2)
컴파일 시간에 핸들러 타입 체크
CROW_ROUTE(app, “/post/<int>”)
([](string a) …
([](int a, int b) …
([](int a) ...
CROW_ROUTE 기능 (3)
여러 종류의 핸들러 지원
[](…)
[](const request& req, …)
[](const request& req, response& res, …)
* 어떻게 여러 종류를 지원하는지에 관해선 나중에 설명 예정
실제 CROW_ROUTE 구현
#define CROW_ROUTE(app, url)
app.route<
crow::black_magic::get_parameter_tag(url)
>(url)
black_magic ???!!!
이름을 말할 수 없는 그분
app.route<get_parameter_tag(url)>(url)
핸들러 형태 체크 → 컴파일 타임 → 템플릿 인자
실행 중에 URL 체크 → 런타임 → 함수 인자
실제 CROW_ROUTE 구현 (2)
app.route<get_parameter_tag(url)>(url)
핸들러 형태 체크 → 컴파일 타임 → 템플릿 인자
실행 중에 URL 체크 → 런타임 → 함수 인자
실제 CROW_ROUTE 구현 (2)
app.route<get_parameter_tag(url)>(url)
핸들러 형태 체크 → 컴파일 타임 → 템플릿 인자
실행 중에 URL 체크 → 런타임 → 함수 인자
실제 CROW_ROUTE 구현 (2)
app.route<get_parameter_tag(url)>(url)
스트링 값(“abc” 등)은 템플릿 인자로 사용할
수 없음
url로 부터 인자에 대한 정보를 얻어
템플릿 인자로 넣을 수 있는 값으로 변환
템플릿 인자부터 ..
constexpr function
constexpr int fact(int n) {
return (n <= 1)
? 1
: fact(n-1)*n;
}
char arr[fact(5)];
constexpr
컴파일 타임에 계산할 수도 있는 함수 또는 값
cin >> n; cout << fact(n); // 런타임
fact(5) == 120, 컴파일 타임에 계산 가능
→ 배열의 크기, 템플릿 인자 등으로 사용 가능
get_parameter_tag
URL 을 받아 인자 정보를 가지는 숫자로 변환
인자가 없는 경우 0
URL 인자는 5종류: <int>=1 <uint>=2 …
6진법으로 표현
(자세한 구현은 생략)
get_parameter_tag
“/”
“/post”
“/post/<int>”
“/near/<int>/<int>”
“/put_score/<double>”
“/wiki/<path>”
0
0
1
11
3
5
숫자에서 다시 타입 리스트 복원
0 → <>
1 → <int>
11 → <int, int>
13 → <double, int>
4 → <string>
5 → <string> * path도 타입은 string
black_magic::S
variadic template으로 타입 리스트를 구현
S<int, double, string> 이 가능
S<a,b>::push<c> === S<c, a, b>
S<a>::push_back<b> === S<a, b>
S<a,b,c>::rebind<Rule> === Rule<a,b,c>
black_magic::S<T…> 구현 (1)
template <typename ... T>
struct S {
template <typename U>
using push = S<U, T...>;
S<a,b>::push<c> === S<c, a, b>
* using A = B; === typedef B A;
black_magic::S<T…> 구현 (2)
template
<template <typename ...> class U>
using rebind = U<T...>;
S<a,b,c>::rebind<Rule> == Rule<a,b,c>
black_magic::arguments<uint64_t>
get_parameter_tag 값을 타입 리스트로
arguments<0>::type == S<>
arguments<3>::type == S<double>
arguments<11>::type == S<int, int>
arguments 구현
template <uint64_t Tag> struct arguments {
using subarg =
typename arguments<Tag/6>::type;
using type =
typename subargs::template push<
typename single_tag_to_type<Tag%6>::type
>;
};
실제로 일어나는 일
argument<31>
subarg = S<double>
type = S<int, double>
arg<3>
subarg = S<>
type = S<double>
partial template specialization
template <int N>
struct single_tag_to_type {};
template <>
struct single_tag_to_type<1> {
using type = int64_t;
};
// C++11은 아니지만..
arguments 구현
template <>
struct arguments<0> {
using type = S<>;
};
URL이 라우팅 규칙이 되기까지
get_parameter_tag(“/<int>/<int>”)
→ arguments<11>
→ S<int, int>
→ TaggedRule<int, int>
Router
vector<unique_ptr<BaseRule>> rules_;
Q&A for Routing 1
get_parameter_tag(“/<int>/<int>”)
→ arguments<11>
→ S<int, int>
→ TaggedRule<int, int>
실제 핸들러 호출하기
Routing 2
남은 문제
/v<uint>/<string>/<path>
“/v2/wiki/example/document”
TaggedRule<uint, string, string>
handler
[](uint32_t ver, string func, string path)
Rule, TaggedRule
최종적으로 호출될 핸들러를 가지고 있음
app.route 의 리턴 값
void handle(
const request& req,
response& res,
const routing_params& params)
Trie based routing
여러 rule 들의 URL을 모아서
요청이 들어왔을 때
어느 Rule에서 처리할 지 판단
트리 구조로 성능 향상
Trie example
GET statuses/home_timeline
GET statuses/retweets/:id
GET statuses/retweets_of_me
POST statuses/retweet/:id
(from Twitter REST API)
statuses/
retweethome_timeline
s/
_of_meuint
uint
/
Trie
add( string url, rule )
find( string url )
-> rule, routing_params
http://en.wikipedia.org/wiki/Trie
routing.h
routing_params
vector<int> int_params;
vector<uint> uint_params;
vector<double> double_params;
vector<string> string_params;
Trie example (1)
/near/<double>/<double>
“/near/37.1/10.1”
routing_params.double_params == {37.1, 10.1}
Trie example (2)
/v<uint>/<string>/<path>
“/v2/wiki/example/document”
routing_params
.uint_params == {2}
.string_params ==
{“wiki”, “example/document”}
핸들러 호출하기
/v<uint>/<string>/<path>
[](unsigned int, string, string)
handler(rp.uint_params[0],
rp.string_params[0],
rp.string_params[1])
compile time
호출부 구현
template <typename CP,
int NInt, int NUint, int NDouble, int NString,
typename S1, typename S2>
struct call;
S1 - URL로 부터 정의된 핸들러 인자 타입의 리스트
S2 - 호출을 위한 타입+인덱스 정보의 리스트
N?? - 인자 처리를 위한 인덱스 값들, CP - 호출 파라미터
TaggedRule<Args…>::handle
void handle(req, res, routing_params) {
call<CallParams, 0, 0, 0, 0, S<Args…>, S<>>(
call_params);
}
call_params
req + res + routing_params + handler
call 호출 과정 - /v<uint>/<string>/<path>
0 0 [uint, str, str] []
1 0 [str, str] [(uint, 0)]
1 1 [str] [(uint, 0) (str, 0)]
1 2 [] [(uint, 0) (str, 0) (str, 1)]
call을 재귀호출
NUint NStr S1 S2
call 호출 과정 - /v<uint>/<string>/<path>
0 0 [uint, str, str] []
NUint NStr S1 S2
call 호출 과정 - /v<uint>/<string>/<path>
0 0 [uint, str, str] []
→ 1 0 [str, str] [<uint, 0>]
NUint NStr S1 S2
struct call<CP, NInt, NUint, NDouble, NString,
S< int64_t, Args1...>, S<Args2...>> {
void operator()(CP cp) {
using pushed = typename S<Args2...>::
template push_back<call_pair<int64_t, NInt>>;
call<CP, NInt+1, NUint, NDouble, NString,
S<Args1...>, pushed>()(cp);
}
};
call 호출 과정 - /v<uint>/<string>/<path>
0 0 [uint, str, str] []
1 0 [str, str] [<uint, 0>]
→ 1 1 [str] [<uint, 0> <str, 0>]
NUint NStr S1 S2
call 호출 과정 - /v<uint>/<string>/<path>
0 0 [uint, str, str] []
1 0 [str, str] [<uint, 0>]
1 1 [str] [<uint, 0> <str, 0>]
→ 1 2 [] [<uint, 0>, <str, 0>, <str, 1>]
NUint NStr S1 S2
struct call<CP, NInt, NUint, NDouble, NString,
S<>, S<Args2...>> {
void operator()(CP cp) {
// 일부 생략
cp.res = cp.handler(
cp.routing_params.template get
<typename Args2::type>(Args2::pos) ...
);
cparams.res.end();
return;
T routing_params::get<T>(index)
template<> string
routing_params::get<string>(index) const
{
return string_params[index];
}
핸들러 호출하기
handler(rp.uint_params[0],
rp.string_params[0],
rp.string_params[1]);
handler(rp.get<uint>(0),
rp.get<string>(0),
rp.get<string>(1));
handler( rp.get<Args2::type>(Args2::pos)... )
핸들러 호출하기
Args… = <uint, 0>, <str, 0>, <str, 1>
handler( rp.get<Args::type>(Args::pos)... )
<uint,0>을 대입한 경우를 보면 = rp.get<uint>(0)
...을 통해서 반복되므로
rp.get<uint>(0), rp.get<str>(1), rp.get<str>(2)
struct call<CP, NInt, NUint, NDouble, NString,
S<>, S<Args2...>> {
void operator()(CP cp) {
// 일부 생략
cp.res = cp.handler(
cp.routing_params.template get
<typename Args2::type>(Args2::pos) ...
);
cparams.res.end();
return;
Variadic template from example
void print(A a, B b, C c, …)
모든 인자를 출력해주는 함수
print()
print(1) - 1
print(2, “hello”, 40) - 2hello40
print 구현
void print() {}
template <typename A, typename ... Args>
void print(A a, Args... args)
{
cout << a;
print(args...);
}
print(2, “hello”, 40) 실행
A = int
Args… = const char*, int
args… = “hello”, 40
cout << 2;
print(“hello”, 40);
print 실행
print<int, const char*, int>(2, “hello”, 40) - 2
print<const char*, int>(“hello”, 40) - hello
print<int>(40) - 40
print()
2hello40
Variadic template 대입의 예
args… = 1, 5, 10
(args+1)… = 1+1, 5+1, 10+1
func(args)… = func(1), func(5), func(10)
func(args…) = func(1, 5, 10)
Q&A for Routing 2
Trie
Routing parameter
Variadic template
Middleware
Middleware?
C 요청 -> S 응답 -> C 받음
요청 --[MW]--> 응답 --[MW]--> 받음
before_handle(req, res)
after_handle(req, res)
Example Middleware
Static page serving (cache control)
Cookie parsing, Session support
JSON parsing
Profiling, Logging
Middleware of express.js (Node.js)
app.use(function (req, res, next) {
req.cookies = parse_cookies(req);
next();
});
req에 임의로 변수추가 가능
Middleware 구현의 제약들
근데 우린 C++이잖아… 변수는 다 선언되어야
unordered_map<string, any> ???
+ express의 문제점: Dependency
세션은 사용하는데 쿠키파서가 없는 경우
이 문제를 어떻게 해결하면 좋을까?
각 MW별로 저장해야할 값들이 존재
어떤 MW는 다른 MW의 값을 참조해야 한다
(C++이니까)
필요한 MW가 빠진 경우 컴파일 에러가 발생해
야함
struct MW::context
MW가 필요한 값을 저장하는 struct
내용에 특별한 제한이 없음
App<A, B, C> app;
A, B, C 세 MW를 사용하는 app
SimpleApp == App<>
Crow에서의 해결 방식
ctx_A : public A::context
ctx_AB : public ctx_A, public B::context
ctx_ABC : public ctx_AB, public C::context
context : public ctx_ABC
실제로 ctx_AB === partial_context<A, B>
context 체인 상속 - App<A, B, C>
Crow에서의 해결 방식
template <typename AllContext>
before_handle(req, res, context& ctx,
AllContext& all_ctx)
from MW - all_ctx.get<A>()
from handler - app.get_context<A>(req)
Crow에서의 해결 방식 - 전체 호출 과정
A::before_handle(req, res, ctx_A)
B::before_handle(req, res, ctx_AB)
C::before_handle(req, res, ctx_ABC)
app.handle(req, res)
C::after_handle(req, res, ctx_ABC)
B::after_handle(req, res, ctx_AB)
A::after_handle(req, res, ctx_A)
Dependency 해결 (1)
Session MW는 Cookie MW에 의존한다면
app<Cookie, Session> - OK
app<Session> - error
app<Session, Cookie> - error
의존: all_ctx.get<Cookie>를 사용한다.
Dependency 해결 (2)
App<A, B, C> app;
A::before_handle(req, res, ctx_A)
B::before_handle(req, res, ctx_AB)
C::before_handle(req, res, ctx_ABC)
app.handle(req, res)
C::after_handle(req, res, ctx_ABC)
B::after_handle(req, res, ctx_AB)
A::after_handle(req, res, ctx_A)
Dependency 해결 (3)
ctx_A :: get<A> - OK
ctx_A :: get<B> - error
ctx_AB :: get<A> - OK
ctx_AB :: get<B> - OK
ctx_AB::get
template <typename T>
typename T::context& get() {
return
static_cast<typename T::context&>(*this);
}
상속한 MW의 context 타입으로만 캐스팅 가능
다른 MW과 연관이 없는 MW라면?
template <typename AllContext>
before_handle(req, res,
context& ctx, AllContext& all_ctx)
대부분의 경우
before_handle(req, res, context& ctx)
SFINAE
Substitution failure is not an error.
템플릿 인자를 대입하는 과정에서 발생하는 에
러는 에러로 간주하지 않는다. (모두 실패하는
경우에는 에러)
또는 이를 이용한 프로그래밍 기법을 지칭함
SFINAE 예제
template <typename T>
true_type has_iterator_checker(typename T::iterator *);
template <typename T>
false_type has_iterator_checker(...);
decltype(has_iterator_checker<int>()) === false_type
decltype(has_iterator_checker<string>()) === true_type
after_call_helper
template <typename MW, typename Context>
void after_call_helper(MW& mw, …,
decltype(
declval<MW>().before_handle(
declval<request&>(), declval<response&>(),
declval<typename MW::context&>(),
declval<Context&>()
))* dummy = 0)
decltype, declval<T>
decltype(X)
X의 선언형
declval<T>()
컴파일 타임에만 사용할 수 있는 T의 객체형
template <typename A, typename B>
auto add(A a, B b) -> decltype(a+b)
{ return a+b; }
template <typename A, typename B>
decltype(declval<A>() + declval<B>())
add(A a, B b)
C++14: return type deduction
after_call_helper
template <typename MW, typename Context>
void after_call_helper(MW& mw, …,
decltype(
declval<MW>().before_handle(
declval<request&>(), declval<response&>(),
declval<typename MW::context&>(),
declval<Context&>()
))* dummy = 0)
after_call_helper
template <typename MW, typename AllContext>
void after_call_helper(MW& mw, …,
decltype(
mw.before_handle(
declval<request&>(), declval<response&>(),
declval<typename MW::context&>(),
declval<AllContext&>()
))* dummy = 0)
after_call_helper
template <typename MW, typename Context>
void after_call_helper(MW& mw, …,
decltype(
mw.after_handle(req, res, ctx, all_ctx)
)
* dummy = 0)
after_call_helper
template <typename MW, typename Context>
void after_call_helper(MW& mw, …,
다음 함수를 호출할 수 있는가?
mw.before_handle(req, res, ctx, all_ctx)
)
after_call_helper
template <typename MW, typename AllContext>
void after_call_helper(MW& mw, …,
decltype(
declval<MW>().after_handle(
declval<request&>(), declval<response&>(),
declval<typename MW::context&>(),
declval<AllContext&>()
))* dummy = 0)
std::enable_if
SFINAE를 이용하기 편하게 만들어둔 도구
조건부로 구현을 선택
template <typename T>
enable_if<is_integral<T>::value> func(T x) …
handler 형태를 고를 때 사용 (생략)
http://en.cppreference.com/w/cpp/types/enable_if
CookieParser - Example Middleware
CookieParser::context
uo_map<string, string> jar,
cookies_to_add;
get_cookie(key)
set_cookie(key, value)
before - 파싱 + jar에 저장
after - Set-Cookie 헤더 추가
Q&A for Middleware
App<A, B, C> app;
context inheritance chain
Middleware call chain
CookieParser
SFINAE
Crow 서버 구조
고려해야 할 점
멀티 쓰레드 작업 배분
Connection 객체의 생성, 소멸 관리
HTTP 타임 아웃 (Keep-Alive)
초기 버전
boost::asio + joyent/http-parser
asio::io_service 하나
concurrency 개수 만큼 io_service.run()
shared_ptr<Connection> 으로 수명 관리
asio::deadline_timer로 타임아웃 처리
초당 처리 횟수가 100,000 이상..
shared_ptr의 atomic 연산이 성능 부하
deadline_timer 내부 자료구조 업데이트 부하
여러 개의 싱글 쓰레드 서버의 결합
N 개의 작업용 쓰레드 (asio::io_service ✕ N)
요청이 들어올 때마다
어느 쓰레드가 처리할지 RR로 분배
해당 요청에 대한 모든 처리는
담당한 쓰레드 안에서만 이루어짐
deadline_timer 성능 저하 문제
각 쓰레드 별로 thread_local한 타이머를 구현
관련 코드: dumb_timer_queue.h
shared_ptr 제거
Connection 객체를 하나의 쓰레드가 담당
atomic 연산 불필요
변경 후 성능 4배 향상
쓰레드간 통신 전혀 없음
* shared_ptr을 쓰지말란 얘기는 아닙니다.
그 외 사용된
C++11 기능들 소개
std::chrono
std::chrono::
system_clock
steady_clock
high_resolution_clock
(거의) 같은 인터페이스 제공
std::chrono 사용법
auto t1 = clock::now();
do_something();
auto t2 = clock::now();
if (t2 - t1 > seconds(10)) …
duration_cast<seconds>(t2 - t1).count()
system_clock
to_time_t, from_time_t 제공
steady_clock
무조건 증가함이 보장됨
high_resolution_clock
제일 높은 해상도를 제공
(가능한 짧은 시간 간격)
operator “”
C++11
std::chrono::seconds(10)
std::chrono::minutes(20)
std::string(“hello”)
C++14
10s
20min
“hello”s
POST request
CROW_ROUTE(app, “/update_score”)
.methods(“POST”_method)
([](const crow::request& req){
auto json = crow::json::load(req.body);
...
});
operator “” _method
constexpr crow::HTTPMethod operator ""
_method(const char* str, size_t len)
{
return
crow::black_magic::is_equ_p(str, "GET", 3)
? crow::HTTPMethod::GET :
…
};
enum class
enum class HTTPMethod
{
GET,
POST,
...
};
int m = HTTPMethod::GET; // error!
사용된 boost 모듈들
asio
lexical_cast
string
iequals
operators
<끝>(내용 발표는)
미리 나온 질문들
현업에서 어디까지 최신 기술을 쓰는게
좋을까요?
현업에서 어디까지 최신 기술...?
C++11 is not bleeding edge
technology. (개인적인 의견)
2011년?
트랜스포머3, 테라, 스카이림, 포탈2
node.js 0.3.3/0.6.6 → 0.12.0, RoR 3.1 → 4.2,
iPhone4 / iOS 5.0, 갤럭시 S2
현업에서 어디까지 최신 기술...?
팀에서 TDD를 사용하기 위해 고려해야할 점?
http://agile.egloos.com/5827377
사회적 자본이 더 중요한 경우가 많다.
C++14 - minor patch to 11
vector v(1000000)
auto lambda = [v = std::move(v), a =
3](auto x, auto y)
{return a + x + y;};
C++14 - minor patch to 11
그외 …
01010b, 1’234’5678’9 == 123456789
make_unique
...
C++14 - minor patch는 훼이크
auto p = [](auto& s, auto...x){
[](...){}((s<<x,1)...);
};
p(cout, 42, "hello?");
위 코드의 실행 결과를 설명하시오. (3점)
rvalue
정확한 얘기를 하려면
lvalue, glvalue, xvalue, rvalue, prvalue를...
http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2010/n305
5.pdf
정확히
rvalue
vector<string> lines;
while(cin) {
string line;
getline(cin, line)
lines.push_back(line);
}
rvalue
vector<string> lines;
while(cin) {
string line;
getline(cin, line)
lines.push_back(std::move(line));
}
string s0("숭");
string s1("그");
string s2("리");
string s3("당");
string s4("당 숭당당");
string dest =
s0 + " " + s1 + " " + s2 + " " + s3 + " " + s4;
rvalue
Strong exception guarantee
vector<T> v1, v2
v1 = std::move(v2);
move_if_noexcept
20150212 c++11 features used in crow

More Related Content

What's hot

Boost 라이브리와 C++11
Boost 라이브리와 C++11Boost 라이브리와 C++11
Boost 라이브리와 C++11
OnGameServer
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심
흥배 최
 
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
Esun Kim
 

What's hot (20)

C++ 11 에 대해서 쉽게 알아봅시다 1부
C++ 11 에 대해서 쉽게 알아봅시다 1부C++ 11 에 대해서 쉽게 알아봅시다 1부
C++ 11 에 대해서 쉽게 알아봅시다 1부
 
Boost
BoostBoost
Boost
 
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
 
C#을 사용한 빠른 툴 개발
C#을 사용한 빠른 툴 개발C#을 사용한 빠른 툴 개발
C#을 사용한 빠른 툴 개발
 
[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?
 
프로그래밍 대회: C++11 이야기
프로그래밍 대회: C++11 이야기프로그래밍 대회: C++11 이야기
프로그래밍 대회: C++11 이야기
 
[C++ Korea 2nd Seminar] C++17 Key Features Summary
[C++ Korea 2nd Seminar] C++17 Key Features Summary[C++ Korea 2nd Seminar] C++17 Key Features Summary
[C++ Korea 2nd Seminar] C++17 Key Features Summary
 
Boost 라이브리와 C++11
Boost 라이브리와 C++11Boost 라이브리와 C++11
Boost 라이브리와 C++11
 
100511 boost&tips 최성기
100511 boost&tips 최성기100511 boost&tips 최성기
100511 boost&tips 최성기
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JS
 
C++11
C++11C++11
C++11
 
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
 
Refelction의 개념과 RTTR 라이브러리
Refelction의 개념과 RTTR 라이브러리Refelction의 개념과 RTTR 라이브러리
Refelction의 개념과 RTTR 라이브러리
 
프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oop프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oop
 
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기
 
Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)
Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)
Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)
 
골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료
 

Viewers also liked

[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기
[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기
[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기
Jaeseung Ha
 
[1116 박민근] c++11에 추가된 새로운 기능들
[1116 박민근] c++11에 추가된 새로운 기능들[1116 박민근] c++11에 추가된 새로운 기능들
[1116 박민근] c++11에 추가된 새로운 기능들
MinGeun Park
 
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기
흥배 최
 

Viewers also liked (19)

[NHN NEXT 14] [Pl in c++] 1. 수업 내용 및 진행 방법
[NHN NEXT 14] [Pl in c++] 1. 수업 내용 및 진행 방법[NHN NEXT 14] [Pl in c++] 1. 수업 내용 및 진행 방법
[NHN NEXT 14] [Pl in c++] 1. 수업 내용 및 진행 방법
 
Visual c++ 오목게임제작
Visual c++ 오목게임제작Visual c++ 오목게임제작
Visual c++ 오목게임제작
 
C++11(최지웅)
C++11(최지웅)C++11(최지웅)
C++11(최지웅)
 
C++11
C++11C++11
C++11
 
c++11
c++11c++11
c++11
 
[C++ adv] c++11
[C++ adv] c++11[C++ adv] c++11
[C++ adv] c++11
 
C++ 타입 추론
C++ 타입 추론C++ 타입 추론
C++ 타입 추론
 
Ndc12 2
Ndc12 2Ndc12 2
Ndc12 2
 
[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기
[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기
[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기
 
초보를 위한 C++11
초보를 위한 C++11초보를 위한 C++11
초보를 위한 C++11
 
[1116 박민근] c++11에 추가된 새로운 기능들
[1116 박민근] c++11에 추가된 새로운 기능들[1116 박민근] c++11에 추가된 새로운 기능들
[1116 박민근] c++11에 추가된 새로운 기능들
 
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기
 
multi-thread 어플리케이션에 대해 모든 개발자가 알아 두지 않으면 안 되는 것
multi-thread 어플리케이션에 대해 모든 개발자가 알아 두지 않으면 안 되는 것multi-thread 어플리케이션에 대해 모든 개발자가 알아 두지 않으면 안 되는 것
multi-thread 어플리케이션에 대해 모든 개발자가 알아 두지 않으면 안 되는 것
 
KGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games Conference
KGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games ConferenceKGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games Conference
KGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games Conference
 
시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?
시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?
시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?
 
Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이 왜 이리 힘드나요? (Lock-free에서 Transactional Memory까지)
Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이  왜 이리 힘드나요?  (Lock-free에서 Transactional Memory까지)Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이  왜 이리 힘드나요?  (Lock-free에서 Transactional Memory까지)
Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이 왜 이리 힘드나요? (Lock-free에서 Transactional Memory까지)
 
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
 
C++11에서 주의해야할 것들
C++11에서 주의해야할 것들C++11에서 주의해야할 것들
C++11에서 주의해야할 것들
 
C++11
C++11C++11
C++11
 

Similar to 20150212 c++11 features used in crow

Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기
지수 윤
 
C Language I
C Language IC Language I
C Language I
Suho Kwon
 
Naver api for android
Naver api for androidNaver api for android
Naver api for android
Sangon Lee
 
나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선
daewon jeong
 
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613
KTH, 케이티하이텔
 

Similar to 20150212 c++11 features used in crow (20)

불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14
 
6 function
6 function6 function
6 function
 
06장 함수
06장 함수06장 함수
06장 함수
 
Deview 2019 눈발자국
Deview 2019 눈발자국Deview 2019 눈발자국
Deview 2019 눈발자국
 
C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2
 
Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기
 
Airflow를 이용한 데이터 Workflow 관리
Airflow를 이용한  데이터 Workflow 관리Airflow를 이용한  데이터 Workflow 관리
Airflow를 이용한 데이터 Workflow 관리
 
포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++
 
C Language I
C Language IC Language I
C Language I
 
Naver api for android
Naver api for androidNaver api for android
Naver api for android
 
Java stream v0.1
Java stream v0.1Java stream v0.1
Java stream v0.1
 
Java stream v0.1
Java stream v0.1Java stream v0.1
Java stream v0.1
 
강의자료 2
강의자료 2강의자료 2
강의자료 2
 
나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선
 
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
 
[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)
 
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613
 
About Visual C++ 10
About  Visual C++ 10About  Visual C++ 10
About Visual C++ 10
 
RNC C++ lecture_4 While, For
RNC C++ lecture_4 While, ForRNC C++ lecture_4 While, For
RNC C++ lecture_4 While, For
 
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
 

20150212 c++11 features used in crow