Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

C++17 Key Features Summary - Ver 2

16 604 vues

Publié le

C++은 10년 만에 C++11/14를 발표하면서 '모던 C++'이라는 이름으로 발전했습니다. 그만큼 새로운 기능들이 많이 추가되었습니다. 그리고 2017년, C++은 C++17이라는 이름으로 또 한 번의 발전을 준비하고 있습니다. 3년 주기로 빠르게 변화하는 모던 C++에 대비하기 위해, C++17에 추가될 주요 기능들을 살펴보고자 합니다.
이 발표는 이전에 발표했던 내용에서 일부 사례 추가 및 최신 내용으로 갱신한 버전입니다.

Publié dans : Technologie
  • Login to see the comments

C++17 Key Features Summary - Ver 2

  1. 1. Nexon Talk 2017 “C++17 Key Features Summary“ (Ver 2) 옥찬호 Nexon Korea, Microsoft MVP utilForever@gmail.com
  2. 2. 소개 • 옥찬호 (Chris Ohk) • Nexon Korea Game Programmer • Microsoft Visual C++ MVP • 페이스북 그룹 C++ Korea 대표 • IT 전문서 집필 및 번역 다수 • 게임샐러드로 코드 한 줄 없이 게임 만들기 (2013) • 유니티 Shader와 Effect 제작 (2014) • 2D 게임 프로그래밍 (2014) • 러스트 핵심 노트 (2017) • 모던 C++ 관련 도서 집필 및 번역중… (2017? 2018?)
  3. 3. 시작하기 전에… Nexon Talk 2017 C++17 • C++17에 추가될 주요 기능들을 설명합니다. • C++17에 추가될 주요 기능 뿐만 아니라, 이후 TS(Technical Specification)에 추가될 기능들도 소개합니다. • C++17에 추가될 기능 중 C++11/14 지식이 필요한 경우, 이해를 돕기 위해 사전 지식을 먼저 설명합니다. • 모든 예제 코드는 발표 이후 Github를 통해 제공됩니다. • Ver 1에서 언급되지 않은 추가 기능들을 소개합니다.
  4. 4. C++17 기능 선호도 조사 Nexon Talk 2017 C++17
  5. 5. C++17 기능 선호도 조사 Nexon Talk 2017 C++17
  6. 6. 현재 표준 C++ 진행 상황 Nexon Talk 2017 C++17
  7. 7. 현재 표준 C++ 진행 상황 Nexon Talk 2017 C++17
  8. 8. C++17 주요 기능 Nexon Talk 2017 C++17 • Folding expressions • New rules for auto deduction from braced-init-list • constexpr lambdas • Lambda capture this by value • Attributes: [[fallthrough]], [[nodiscard]], [[maybe_unused]] • inline variables • namespace A::B
  9. 9. C++17 주요 기능 Nexon Talk 2017 C++17 • Structured bindings • constexpr if • if (init; condition), switch (init; condition) • std::any, std::optional, std::variant, std::string_view • std::invoke, std::apply • try_emplace and insert_or_assign for std::map • File System TS v1, Parallelism TS v1
  10. 10. Folding expression Nexon Talk 2017 C++17 • C++11의 가변 템플릿 (Variadic Template) template <typename T> void PrintList(T value) { std::cout << value << std::endl; } template<typename First, typename ...Rest> void PrintList(First first, Rest ...rest) { std::cout << first << ", "; PrintList(rest...); }
  11. 11. Folding expression Nexon Talk 2017 C++17 • C++11의 가변 템플릿 (Variadic Template) PrintList(42, "Hello", 2.3, 'a'); 42, Hello, 2.3, a PrintList(first = 42, ...rest = “hello“, 2.3, 'a'); 42 PrintList(first = 42, ...rest = 2.3, 'a'); hello PrintList(first = 42, ...rest = 'a'); 2.3 PrintList(first = 'a'); 재귀 함수를 끝내기 위한 별도의 함수 필요! template <typename T> void PrintList(T value) { std::cout << value << std::endl; }
  12. 12. Folding expression Nexon Talk 2017 C++17 • 가변 템플릿을 사용해 표현식을 간단하게 구현할 수 있는 기능 Fold = 접는다, Expression = 표현식 → “표현식을 접는다!” template<typename... Args> bool All(Args... args) { return (... && args); } int main() { // ((true && true) && true) && false bool b = All(true, true, true, false); } (…) && false ((…) && true) && false (((…) && true) && true) && false ((true && true) && true) && false
  13. 13. Folding expression Nexon Talk 2017 C++17 • Folding expression 문법 1. Unary right fold (E op …) → E1 op (… op (En-1 op En)) 2. Unary left fold (… op E) → ((E1 op E2) op …) op En 3. Binary right fold (E op … op l) → E1 op (… op (En-1 op (En on l))) 4. Binary left fold (l op … op E) → (((l op E1) op E2) op …) op En
  14. 14. Folding expression Nexon Talk 2017 C++17 • Example 1 : Binary right fold (E op … op l) template<typename ...Args> int Sum(Args&&... args) { return (args + ... + (1 * 2)); } int main() { Sum(1, 2, 3, 4); }
  15. 15. Folding expression Nexon Talk 2017 C++17 • Example 2 : Binary left fold (l op … op E) template<typename ...Args> void Printer(Args&&... args) { (std::cout << ... << args) << 'n'; } int main() { Printer(1, 2, 3, "abc"); }
  16. 16. New rules: auto deduction Nexon Talk 2017 C++17 • C++11의 문제 : auto와 {}로 인해 발생하는 모호함 int main() { int v1{ 123 }; // 1 auto v2{ 123 }; // 2 auto v3 = { 123 }; // 3 auto v4{ 1, 2, 3 }; // 4 auto v5 = { 1, 2, 3 }; // 5 } int std::initializer_list<int> std::initializer_list<int> std::initializer_list<int> std::initializer_list<int> int main() { int v1{ 123 }; // int auto v2{ 123 }; // std::initializer_list<int> auto v5 = { 1, 2, 3 }; // std::initializer_list<int> }
  17. 17. New rules: auto deduction Nexon Talk 2017 C++17 • C++17에서는 auto와 {}를 통한 초기화 리스트의 모호함을 제거함 int main() { auto x1{ 1 }; // int auto x2 = { 2 }; // initializer_list<int> auto x3 = { 1,2 }; // initializer_list<int> auto x4{ 1,2 }; // error }
  18. 18. constexpr lambdas Nexon Talk 2017 C++17 • C++11의 상수 표현식 (constexpr, Constant Expression) • 쉽게 구현할 수 있는 메타 프로그래밍 • 변수의 값이나 함수의 내용을 컴파일 타임에 처리 • 함수 내에서는 하나의 표현식만 사용할 수 있고 반드시 리터럴 타입을 반환해야 했지만, C++14에서 제한이 다소 완화됨 constexpr int n = 0; // OK constexpr int m = time(NULL); // error C2127 constexpr int square(int x) { return x * x; } int n; std::cin >> n; square(n); // Processed in run-time square(10); // Processed in compile-time
  19. 19. constexpr lambdas Nexon Talk 2017 C++17 • C++11의 람다식 (Lambda Expression) [my_mod] (int v) -> int { return v % my_mod; } 개시자 (Introducer Capture) 인자 (Arguments) 반환 타입 (Return Type) 함수의 몸통 (Statement)
  20. 20. constexpr lambdas Nexon Talk 2017 C++17 • C++11의 람다식 (Lambda Expression) int x = 10, y = 20; [] {}; // Do not capture [x](int arg) { return x; }; // value(Copy) capture x [=] { return x; }; // value(Copy) capture all [&] { return y; }; // reference capture all [&, x] { return y; }; // reference capture all except x [=, &y] { return x; }; // value(Copy) capture all except y [this] { return this->something; }; // this capture [=, x] {}; // error [&, &x] {}; // error [=, this] {}; // error [x, x] {}; // error
  21. 21. constexpr lambdas Nexon Talk 2017 C++17 • “람다식에 constexpr을 허하노라!” int main() { constexpr auto add = [](int a, int b) { return a + b; }; Test<add(1, 2)> t1; auto add2 = [](int a, int b) constexpr { return a + b; }; Test<add2(1, 2)> t2; auto add3 = [](int a, int b) { return a + b; }; constexpr int c = add3(1, 2); constexpr int(*f)(int, int) = add3; Test<add3(1, 2)> t3; }
  22. 22. constexpr lambdas Nexon Talk 2017 C++17 • Example : 팩토리얼 int main() { constexpr auto Factorial = getFactorializer(); static_assert(Factorial(5) == 120, ""); static_assert(Factorial(10) == 3628800, ""); }
  23. 23. constexpr lambdas Nexon Talk 2017 C++17 constexpr auto getFactorializer = [] { unsigned int optimization[6] = {}; auto for_each = [](auto* b, auto* e, auto pred) { auto* it = b; while (it != e) pred(it++ - b); }; for_each(optimization, optimization + 6, [&](int n) { if (!n) optimization[n] = 1; else optimization[n] = n * optimization[n - 1]; }); auto FacImpl = [=](auto fac, unsigned n) { if (n <= 5) return optimization[n]; return n * fac(fac, n - 1); }; auto Fact = [=](int n) { return FacImpl(FacImpl, n); }; return Fact; };
  24. 24. this capture by value Nexon Talk 2017 C++17 • C++11에서는 레퍼런스에 의한 this 캡처만 지원했었음 • C++17부터는 값에 의한 this 캡처를 지원함 struct MyObj { int value{ 123 }; auto getValueCopy() { return [*this]{ return value; }; } auto getValueRef() { return [this]{ return value; }; } }; MyObj mo; auto valueCopy = mo.getValueCopy(); auto valueRef = mo.getValueRef(); mo.value = 321; valueCopy(); // 123 valueRef(); // 321
  25. 25. Attributes Nexon Talk 2017 C++17 • 타입, 개체, 코드 등에 구현 정의 특성을 부여 • C++14에 추가된 특성 • [[noreturn]] : 이 함수는 리턴하지 않음 • [[carries_dependency]] : 종속성 체인이 함수 안팎으로 전파됨 • [[deprecated]] : 사용할 수 있지만, 권장하지 않음 (더이상 사용 X) • C++17에 추가된 특성 • [[fallthrough]] : switch-case 문에서 사용, 완료되지 않음을 나타냄 • [[nodiscard]] : 함수의 리턴 값이 있는데 버리는 경우 경고문을 표시 • [[maybe_unused]] : 사용하지 않는 변수에 대해 경고문을 표시하지 않음
  26. 26. Attributes Nexon Talk 2017 C++17 • Example 1 : [[noreturn]] - 이 함수는 리턴하지 않음 • [[noreturn]] void f() { throw "error"; // OK } [[noreturn]] void q(int i) { // behavior is undefined // if called with an argument <= 0 if (i > 0) { throw "positive"; } }
  27. 27. void f(int n) { void g(), h(), i(); switch (n) { case 1: case 2: g(); [[fallthrough]]; case 3: // no warning on fallthrough h(); case 4: // compiler may warn on fallthrough i(); [[fallthrough]]; // illformed, not before a case label } } Attributes Nexon Talk 2017 C++17 • Example 2 : [[fallthrough]] - switch-case 문에서 사용, 완료되지 않음을 나타냄
  28. 28. struct [[nodiscard]] error_info { }; error_info enable_missile_safety_mode(); void launch_missiles(); void test_missiles() { enable_missile_safety_mode(); // compiler may warn // on discarding a nodiscard value launch_missiles(); } error_info& foo(); void f1() { foo(); // nodiscard type is not returned by value, no warning } Attributes Nexon Talk 2017 C++17 • Example 3 : [[nodiscard]] - 함수의 리턴 값이 있는데 버리는 경우 경고문을 표시
  29. 29. Attributes Nexon Talk 2017 C++17 • Example 4 : [[maybe_unused]] - 사용하지 않는 변수에 대해 경고문을 표시하지 않음 [[maybe_unused]] void f([[maybe_unused]] bool thing1, [[maybe_unused]] bool thing2) { [[maybe_unused]] bool b = thing1 && thing2; assert(b); // in release mode, assert is compiled out, and b is unused // no warning because it is declared [[maybe_unused]] } // parameters thing1 and thing2 are not used, no warning
  30. 30. inline variables Nexon Talk 2017 C++17 • 클래스 템플릿에서 static 변수를 지원하는 편리한 방법 // until C++14 template <class Dummy> struct Kath_ { static std::string const hi; }; template <class Dummy> std::string const Kath_<Dummy>::hi = “Zzzzz..."; using Kath = Kath_<void>; // Allows you to write `Kath::hi`.
  31. 31. inline variables Nexon Talk 2017 C++17 • 클래스 템플릿에서 static 변수를 지원하는 편리한 방법 // since C++17 struct Kath { static std::string const hi; }; template <class Dummy> inline std::string const Kath::hi = “Zzzzz..."; // Simpler!
  32. 32. inline variables Nexon Talk 2017 C++17 • 클래스 템플릿에서 static 변수를 지원하는 편리한 방법 // since C++17 struct Kath { static inline std::string const hi = “Zzzzz..."; // Simplest! }; “An inline static data member can be defined in the class definition and may specify a brace-or-equal-initializer. If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see D.X). Declarations of other static data members shall not specify a brace-or-equal-initializer.”
  33. 33. namespace A::B Nexon Talk 2017 C++17 • 네임스페이스를 중첩해서 사용할 수 있는 기능 // until C++14 namespace A { namespace B { namespace C { // ... } } } // since C++17 namespace A::B::C { // ... }
  34. 34. Structured bindings Nexon Talk 2017 C++17 • 드디어 사용할 수 있는 다중 반환! (사실은 Tuple-like objects…) using Coordinate = std::pair<int, int>; Coordinate origin() { return Coordinate{ 0, 0 }; } const auto[x, y] = origin(); x; // == 0 y; // == 0
  35. 35. constexpr if Nexon Talk 2017 C++17 • static if의 C++ 버전, 특정 블록만 컴파일 할 수 있는 기능 template <typename T> constexpr bool isIntegral() { if constexpr (std::is_integral<T>::value) return true; else return false; } static_assert(isIntegral<int>() == true); static_assert(isIntegral<char>() == true); static_assert(isIntegral<double>() == false); struct S {}; static_assert(isIntegral<S>() == false);
  36. 36. if (init; condition) Nexon Talk 2017 C++17 • if 문에 초기화 구문을 포함할 수 있는 기능 → 공통적으로 사용하는 코드 패턴을 단순화하고 스코프를 타이트하게 유지 // until C++14 { std::lock_guard<std::mutex> lk(mx); if (v.empty()) v.push_back(val); } // since C++17 { if (std::lock_guard<std::mutex> lk(mx); v.empty()) v.push_back(val); }
  37. 37. switch (init; condition) Nexon Talk 2017 C++17 • switch 문에 초기화 구문을 포함할 수 있는 기능 → 공통적으로 사용하는 코드 패턴을 단순화하고 스코프를 타이트하게 유지 // until C++14 Foo gadget(args); switch (auto s = gadget.status()) { case OK: gadget.zip(); break; case Bad: throw BadFoo(s.message()); } // since C++17 switch (Foo gadget(args); auto s = gadget.status()) { case OK: gadget.zip(); break; case Bad: throw BadFoo(s.message()); }
  38. 38. std::any Nexon Talk 2017 C++17 • Boost.any 기반 라이브러리 • 모든 종류의 정보를 저장 (단, 복사 생성자를 지원해야 함) • any_cast()를 통해 원하는 타입으로 변환된 결과를 얻을 수 있음 void foo(std::any a) { double d = std::any_cast<double>(a); std::cout << d << std::endl; } int main() { foo(3.4); }
  39. 39. std::optional Nexon Talk 2017 C++17 • Boost.optional 기반 라이브러리 • 함수에서 “유효하지 않은 값”을 리턴하기 위해 만들어짐 std::optional<int> Sqrt(int x) { if (x < 0) return std::optional<int>(); int i = 0; for (i = 0; i * i <= x; ++i) { } return std::optional<int>(i - 1); } int main() { for (int i = -5; i <= 5; ++i) { std::optional<int> x = Sqrt(i); if (x) std::cout << *x << std::endl; else std::cout << "Invalidn"; } }
  40. 40. std::variant Nexon Talk 2017 C++17 • Boost.variant 기반 라이브러리 • 타입 세이프한 union을 나타냄 • boost::any와는 다르게 지정된 형태로만 될 수 있으며, 타입 변환 시 동적 할당을 사용하지 않기에 성능이 좀 더 뛰어남 std::variant<int, double> v{ 12 }; std::get<int>(v); // == 12 std::get<0>(v); // == 12 v = 12.0; std::get<double>(v); // == 12.0 std::get<1>(v); // == 12.0
  41. 41. std::variant Nexon Talk 2017 C++17 • Example : State Machine struct Connection { std::string m_serverAddress; struct Disconnected {}; struct Connecting {}; struct Connected { std::chrono::system_clock::time_point m_connectedTime; std::optional<std::chrono::milliseconds> m_lastPingTime; }; struct ConnectionInterrupted { std::chrono::system_clock::time_point m_disconnectedTime; }; variant<Disconnected, Connecting, Connected, ConnectionInterrupted> m_connection; };
  42. 42. std::variant Nexon Talk 2017 C++17 • Example : State Machine using State = std::variant<Disconnected, Connecting, Connected, ConnectionInterrupted>; struct InterruptedEvent { InterruptedEvent(Connection& c) : m_c(c) {} State operator()(const Disconnected&) { return Disconnected(); } State operator()(const Connecting&) { return Disconnected(); } State operator()(const Connected&) { const auto now = std::chrono::system_clock::now(); m_c.notifyInterrupted(now); return ConnectionInterrupted{ now }; } State operator()(const ConnectionInterrupted& s) { return s; } private: Connection& m_c; };
  43. 43. std::string_view Nexon Talk 2017 C++17 • 문자열에 대해 소유하지 않는 레퍼런스 • 다른 어딘가에서 소유하고 있는 문자열의 복사를 피하기 위함 • 문자열 상단에 추상화를 제공하는데 유용하게 사용 (예 : 파싱) std::string str{ " trim me" }; std::string_view v{ str }; v.remove_prefix(std::min(v.find_first_not_of(" "), v.size())); str; // == " trim me“ v; // == "trim me"
  44. 44. std::invoke Nexon Talk 2017 C++17 • 함수와 인자를 받아 대신 실행해주는 함수 template <typename Callable> class Proxy { Callable c; public: Proxy(Callable c) : c(c) {} template <class... Args> decltype(auto) operator()(Args&&... args) { return std::invoke(c, std::forward<Args>(args)...); } }; auto add = [](int x, int y) { return x + y; }; Proxy<decltype(add)> p{ add }; p(1, 2); // == 3
  45. 45. std::apply Nexon Talk 2017 C++17 • std::invoke와 똑같은 동작을 하는 함수 • 차이점이라면 가변 인자로 받지 않고 std::tuple로 받음 auto add = [](int x, int y) { return x + y; }; std::apply(add, std::make_tuple(1, 2)); // == 3 void print(std::string i, std::string j) { std::cout << i << " " << j << std::endl; } std::tuple<std::string, std::string> t{ "ab", "cd" }; std::apply(print, t);
  46. 46. std::map<std::string, std::string> userMap; userMap.insert(std::make_pair("Kim123", "Kim")); userMap.emplace("Lee123", "Lee"); userMap.try_emplace("Yun123", "Yun"); std::map::try_emplace Nexon Talk 2017 C++17 • 키와 값을 모두 메모리에 직접 생성하는 함수 (std::map::insert와 std::map::emplace와는 다름) • 키가 이미 존재하는 경우, 아무 일도 하지 않음
  47. 47. std::map::insert_or_assign Nexon Talk 2017 C++17 • 키가 존재하지 않는 경우, std::map::insert처럼 새 값을 삽입 • 키가 존재하는 경우, std::forward<Value>(obj)를 할당 std::map<char, int> mp{ { 'B', 1256 } }; mp.insert_or_assign('A', 890); // The data is inserted since no key with ‘A’ // exist in the container for (auto elem : mp) { std::cout << elem.first << " " << elem.second << std::endl; } mp.insert_or_assign('B', 7584); // 7584 is assigned to the value of the pair // with the key as ‘B’ std::cout << mp['B'] << std::endl; // Returns the newly assign value
  48. 48. Filesystem TS v1 Nexon Talk 2017 C++17 • Boost.filesystem 기반 라이브러리 • 파일, 경로, 디렉터리와 관련된 작업들을 수행할 수 있음 namespace fs = std::experimental::filesystem; int main() { fs::create_directories("sandbox/a/b"); std::ofstream("sandbox/file1.txt"); std::ofstream("sandbox/file2.txt"); for (auto& p : fs::directory_iterator("sandbox")) std::cout << p << 'n'; fs::remove_all("sandbox"); }
  49. 49. // sort with dynamically-selected execution size_t threshold = 30; execution_policy exec = seq; if (v.size() > threshold) { exec = par; } sort(exec, v.begin(), v.end()); Parallelism TS v1 Nexon Talk 2017 C++17 • 순차적인 STL 처리 → 병렬적인 STL 처리 vector<int> v = { 1,2,3 }; // standard sequential sort sort(v.begin(), v.end()); // explicitly sequential sort sort(seq, v.begin(), v.end()); // permitting parallel execution sort(par, v.begin(), v.end()); // permitting vectorization as well sort(par_vec, v.begin(), v.end());
  50. 50. Removed keywords Nexon Talk 2017 C++17 • C++17부터 지원하지 않는 키워드들 // 1. register register int a; // 2. bool increment bool b = 0; ++b; // bool increment // 3. auto_ptr auto_ptr<int> ap; // 4. random_shuffle int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; random_shuffle(x, x + 10);
  51. 51. 다루지 않은 C++17의 새 기능 Nexon Talk 2017 C++17 • Template argument deduction for class templates • Declaring non-type template parameters with auto • UTF-8 character literals • Direct-list-initialization of enums • std::byte type • Splicing for maps and sets • And so on…
  52. 52. C++17 이후 논의중인 기능들 Nexon Talk 2017 C++17 • Unified call syntax • operator. (Dot) • Contract • And so on…
  53. 53. Unified call syntax Nexon Talk 2017 C++17 • 함수 호출 문법의 개선, .으로부터 봉인 해제! class Test { public: void foo(int a) { } }; int main() { vector<int> v1; vector<int> v2; v1.swap(v2); swap(v1, v2); Test t; t.foo(1); // ok .. foo(t, 1); // ok in the future }
  54. 54. template<class X> class Ref { public: Ref(int a) : p{ new X{ a } } {} X& operator.() { /* maybe some code here */ return *p; } ~Ref() { delete p; } void rebind(X* pp) { delete p; p = pp; } // ... private: X* p; }; Ref<X> x{ 99 }; x.f(); // means (x.operator.()).f() means (*x.p).f() x = X{ 9 }; // means x.operator.() = X{9} means (*x.p) = X{9} operator. (Dot) Nexon Talk 2017 C++17 • .도 연산자 오버로딩 할 수 있는 시대! → “Smart Reference”
  55. 55. Contract Nexon Talk 2017 C++17 • 우리는 늘 버그와 싸운다!
  56. 56. Contract Nexon Talk 2017 C++17 • 그래서 우리가 사용하는 방법, assert() void print_number(int* myInt) { assert(myInt != nullptr); std::cout << *myInt << "n"; } int main() { int a = 10; int *b = nullptr, *c = nullptr; b = &a; print_number(b); print_number(c); }
  57. 57. Contract Nexon Talk 2017 C++17 • 계약(Contract)이란, 함수 앞에 사전 조건과 사후 조건을 추가해 assert()처럼 특정 조건을 만족하는지 검사할 수 있는 기능 (assert()보다 가독성이 좋아 더 직관적이다) • 사전 조건 (Pre-condition) : expects • 사후 조건 (Post-condition) : ensures template<typename T> class ArrayView { T& operator[](size_t i)[[expects:i < size()]]; ArrayView(const vector<T>& v)[[ensures:data() == v.data()]]; };
  58. 58. struct A { bool f() const; bool g() const; virtual std::string bhar()[[expects:f() && g()]]; virtual int hash()[[ensures:g()]]; virtual void gash()[[expects:g()]]; virtual double fash(int i) const[[expects:i > 0]]; }; struct B : A { std::string bhar() override[[expects:f()]]; // ERROR: weakening. int hash() override[[ensures:f() && g()]]; // ERROR: strengthening. void gash() override[[expects:g()]]; // OK: repeat from base. double fash(int) override; // OK: inherited from base. }; Contract Nexon Talk 2017 C++17 • Example : expects와 ensures의 사용 방법 이해
  59. 59. C++17 이후 (아마) 추가될 TS Nexon Talk 2017 C++17 • Concept TS • Range TS • Networking TS • Coroutine TS • Module TS • Graphics TS • Reflection TS
  60. 60. Concept TS Nexon Talk 2017 C++17 • 다음 코드의 출력 결과는? #include <algorithm> #include <list> int main() { std::list<int> l = { 2, 1, 3 }; std::sort(l.begin(), l.end()); }
  61. 61. Concept TS Nexon Talk 2017 C++17 • 다음 코드의 출력 결과는?
  62. 62. Concept TS Nexon Talk 2017 C++17 • 오류의 발생 원인 • template <class RandomIt> void sort(RandomIt first, RandomIt last); • 여기서 RandomIt는 ValueSwappable과 RandomAccessIterator의 제약 사항을 만족해야 함 → 하지만 int에는 반복자(Iterator)가 존재하지 않는다! std::list<int> l = { 2, 1, 3 }; std::sort(l.begin(), l.end());
  63. 63. Concept TS Nexon Talk 2017 C++17 • C#에서는 제약 사항과 관련해 다양한 클래스와 인터페이스를 제공 • ICloneable • IComparable • IConvertible • IFormattable • Nullable • … • C++에서는? … → Concept의 등장!
  64. 64. template <class T> concept bool EqualityComparable() { return requires(T a, T b) { {a == b}->Boolean; // Boolean is the concept defining {a != b}->Boolean; // a type usable in boolean context }; } Concept TS Nexon Talk 2017 C++17 • C++ 템플릿의 확장 기능 → 템플릿 매개 변수에 제약을 건다! void f(const EqualityComparable&); f("abc"s); // OK, std::string satisfies EqualityComparable // Error: not EqualityComparable f(std::use_facet<std::ctype<char>>(std::locale{}));
  65. 65. Concept TS Nexon Talk 2017 C++17 • 이제 컴파일러의 오류 메시지가 명확해진다! In instantiation of 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = std::_List_iterator<int>; _Compare = __gnu_cxx::__ops::_Iter_less_iter]': error: no match for 'operator-' (operand types are 'std::_List_iterator<int>' and 'std::_List_iterator<int>') std::__lg(__last - __first) * 2, error: cannot call function 'void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]' note: concept 'RandomAccessIterator()' was not satisfied
  66. 66. Concept TS Nexon Talk 2017 C++17 • Concept 리스트 • Basic • DefaultConstructible, MoveConstructible, CopyConstructible, MoveAssignable, CopyAssignable, Destructible • Library-wide • EqualityComparable, LessThanComparable, Swappable, ValueSwappable, NullablePointer, Hash, Allocator, FunctionObject, Callable, Predicate, • Iterator • InputIterator, OutputIterator, ForwardIterator, BidirectionalIterator, RandomAccessIterator, ContiguousIterator
  67. 67. Range TS Nexon Talk 2017 C++17 • 범위를 다루는 제너릭 라이브러리 • 명세 문서 : https://ericniebler.github.io/std/wg21/D4128.html • 구현 파일 : https://github.com/ericniebler/range-v3 • Range의 장점 • 편의성 (Convenience) : 짧아지는 코드 • 느긋한 계산 (Lazy Evaluation) : 무한 범위 표현 가능, 불필요한 계산 회피 • 조합성 (Composability) : 직관적인 표현 가능, 코드 생산성 향상
  68. 68. Range TS Nexon Talk 2017 C++17 • Example : [0 ~ 15) 에서 5개씩 그룹을 지어 각 그룹의 합을 구하기 • 0 + 1 + 2 + 3 + 4 = 10 • 5 + 6 + 7 + 8 + 9 = 35 • … vector<int> v = view::iota(0, 15) | view::group_by(quotient) | view::transform(sum); for (auto e : v) cout << e << " "; cout << endl; auto quotient = [](int a, int b) { return a / 5 == b / 5; }; auto sum = [](auto rng) { return ranges::accumulaate(rng, 0); };
  69. 69. Range TS Nexon Talk 2017 C++17 • Example : 피타고라스 수 • 𝑎𝑎2 + 𝑏𝑏2 = 𝑐𝑐2 을 만족하는 세 자연수 쌍 𝑎𝑎, 𝑏𝑏, 𝑐𝑐 100개 구하기 auto triples = view::ints(1) >>= [] (int z) { return view::ints(1, z + 1) >>= [=](int x) { return view::ints(x, z + 1) >>= [=](int y) { return yield_if(x*x + y*y == z*z, std::make_tuple(x, y, z)); }; }; };
  70. 70. Networking TS Nexon Talk 2017 C++17 • Boost.asio 기반 라이브러리 • 명세 문서 : https://github.com/chriskohlhoff/networking-ts • 구현 파일 : https://github.com/chriskohlhoff/networking-ts-impl try { io_service io_service; tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 13)); for (;;) { tcp::socket socket(io_service); acceptor.accept(socket); string message = make_daytime_string(); boost::system::error_code ignored_error; boost::asio::write(socket, boost::asio::buffer(message), ignored_error); } } catch (std::exception& e) { std::cerr << e.what() << std::endl; }
  71. 71. Coroutine TS Nexon Talk 2017 C++17 • Stackless Resumable Functions • Lightweight, customizable coroutines • Targeted to another technical specifications • Experimental implementation in Visual Studio 2015 Update 1 • 2 × 2 × 2 • 새로운 키워드 2개 : await, yield • 새로운 컨셉 2개 : Awaitable, Coroutine Promise • 새로운 타입 2개 : resumable_handle, resumable_traits
  72. 72. Coroutine TS Nexon Talk 2017 C++17 • Example 1 : 비동기 작업 (Asynchronous Operations) // this could be some long running computation or I/O future<int> CalculateTheAnswer() { return std::async([] { this_thread::sleep_for(1s); return 42; }); } // Here is a resumable function future<void> Coroutine() { std::cout << "Started waiting... n"; auto result = __await CalculateTheAnswer(); std::cout << "Got " << result << "n"; } int main() { Coroutine().get(); }
  73. 73. Coroutine TS Nexon Talk 2017 C++17 • Example 2 : 제너레이터 패턴 (Generator Pattern) generator<int> Fibonacci() { int a = 0; int b = 1; for (;;) { __yield_value a; auto next = a + b; a = b; b = next; } } int main() { for (auto v : Fibonacci()) { if (v > 50) break; cout << v << endl; } }
  74. 74. Module TS Nexon Talk 2017 C++17 • C++에서는 #include를 통해 헤더 파일을 포함 • 문제는 헤더 파일 안에 있는 모든 부분을 포함한다는 것! (포함하고 싶지 않은 부분도 가져오게 됨) • 다른 언어에서는 필요한 부분만 가져올 수 있는 기능을 제공 • C# : using System.Linq; • Java : import java.util.Scanner; • Python : from path import pi • C++에서는? … → Module의 등장!
  75. 75. Module TS Nexon Talk 2017 C++17 • 모듈에서 기억해야 할 3가지 키워드! • module : 모듈로 정의할 이름을 지정 Ex) module M1 : 정의할 모듈의 이름은 M1이다. • import : 가져올 모듈의 이름을 지정 Ex) import M1 : 가져올 모듈의 이름은 M1이다. • export : 내보낼 함수의 인터페이스를 지정 Ex) export int f(int, int) : 내보낼 함수의 이름은 f이고 리턴 타입은 int, 매개 변수는 (int, int)다.
  76. 76. Module TS Nexon Talk 2017 C++17 • Example : 두 cpp 파일에서 모듈을 정의해 다른 cpp 파일에서 사용 // m1.cpp module M1; export int f(int, int); int g(int x) { return x * x; } int f(int x, int y) { return g(x) + g(y); } // m2.cpp module M2; export bool g(int, int); import std.math; int f(int x, int y) { return x + y; } int g(int x, int y) { return f(abs(x), abs(y)); } // main.cpp import M1; import M2; import std.vector; int main() { return f(3, 4) + g(3, 4); }
  77. 77. Graphics TS Nexon Talk 2017 C++17 • 2D 그래픽 렌더링 및 표시를 위한 라이브러리 • 명세 문서 및 구현 파일 : https://github.com/mikebmcl/N3888_RefImpl #include <experimental/io2d> using namespace std::experimental::io2d; int main() { auto ds = make_display_surface(640, 480, format::argb32); ds.draw_callback([](display_surface& ds) { ds.paint(rgba_color::firebrick()); ds.render_text("Hello world!", { 50.0, 50.0 }, rgba_color::aqua()); }); return ds.show(); }
  78. 78. Reflection TS Nexon Talk 2017 C++17 • 컴파일 타임 기반 Static Reflection • 명세 문서 및 구현 파일 : https://github.com/matus-chochlik/mirror typedef reflexpr(unsigned) meta_unsigned; static_assert(is_metaobject_v<meta_unsigned>, ""); static_assert(meta::is_type_v<meta_unsigned>, ""); static_assert(!meta::is_alias_v<meta_unsigned>, ""); static_assert(is_same_v< meta::get_reflected_type_t<meta_unsigned>, unsigned>, ""); static_assert(meta::has_name_v<meta_unsigned>, ""); cout << meta::get_name_v<meta_unsigned> << endl; typedef reflexpr(unsigned*) meta_ptr_unsigned; static_assert(meta::has_name_v<meta_ptr_unsigned>, ""); cout << meta::get_name_v<meta_ptr_unsigned> << endl;
  79. 79. Recommend C++ books Nexon Talk 2017 C++17 • The C++ Programming Language, 4th Edition • Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14 • Discovering Modern C++ • The C++ Standard Library: A Tutorial and Reference (2nd Edition) • Optimized C++: Proven Techniques for Heightened Performance • C++ Concurrency in Action: Practical Multithreading • A Tour of C++ (C++ In-Depth)
  80. 80. Summary Nexon Talk 2017 C++17 • C++17 표준화 작업이 완료되었습니다. 이제는 C++20을 향해… • 소개한 기능 외에도 다양한 추가 / 변경 사항들이 있습니다. • 새 기능이 추가되었다고 무조건 다 알아야 할 필요는 없습니다. • 모던 C++의 기능을 무조건 사용하기보다는, 어떤 기능인지 파악하고 필요한 곳에 적절히 사용합시다.
  81. 81. References Nexon Talk 2017 C++17 • http://www.cplusplus.com/reference • http://en.cppreference.com • http://www.isocpp.org • http://www.open-std.org • https://github.com/ericniebler/range-v3 • https://github.com/chriskohlhoff/networking-ts-impl • https://github.com/mikebmcl/N3888_RefImpl • https://github.com/matus-chochlik/mirror
  82. 82. References Nexon Talk 2017 C++17 • http://khuttun.github.io/2017/02/04/implementing-state-machines- with-std-variant.html • https://github.com/AnthonyCalandra/modern-cpp-features • https://github.com/fffaraz/awesome-cpp
  83. 83. 감사합니다 http://github.com/utilForever 질문 환영합니다!

×