본문 바로가기

C++38

람다표현식에서 기본 갈무리 모드는 피하자 C++11의 기본 갈무리 모드는 두가지로 하나는 참조에 의한 갈무리 모드, 또 하나는 값에 의한 갈무리 모드이다. 기본 참조에 의한 갈무리 모드는 참조 대상을 잃을 위험이 있으며, 값에 의한 갈무리 모드 또한 참조가 대상을 잃는 문제를 갖고있으며, 자기 완결적이지 않은 경우가 있다. 참조 갈무리를 사용하는 클로저는 지역 변수 또는 람다가 정의된 범위에서 볼 수 있는 매개변수에 대한 참조를 가지게 된다. 람다에 의해 생성된 클로저의 수명이 그 지역변수나 매개변수의 수명보다 오래 지속되면, 클로저 안의 참조는 대상을 잃는다. 예를들어 int 하나를 받아 그 값이 필터를 만족하는지 뜻하는 bool 하나를 돌려주는 필터링 함수들을 담는 컨테이너가 있다고 하자 using FilterContainer = std::.. 2020. 8. 3.
완벽전달이 실패하는 경우들 2 중복적재된 함수 이름과 템플릿 이름 1편에서의 함수 f와 마찬가지로 fwd를 거쳐 인수를 전달하려는 대상 함수의 행동 방식을 커스텀 하기위해 f가 하나의 함수를 받아서 그 함수를 호출한다고 하자. 그함수가 int를 받고 int를 돌려준다고 하자 void f(int (*pf)(int));// pf는 processing function void f(int pf(int));// 더 간단한 비 포인터 구문 여기에 중복 적재된 processVal 함수가 있다고 하자 int processVal(int value); int processVal(int value, int priority); f(processVal);// 가능하다 f는 함수 포인터를 기대하지만 processVal은 함수 포인터가 아니다. 함수또한 아니다.. 2020. 7. 30.
완벽 전달이 실패하는 경우들 1 우선 완벽 전달에 대해 알아보도록 하자 전달(forwarding)이란 말 그대로 한 함수가 자신의 인수들을 다른 함수에 넘겨주는(전달하는) 것을 뜻한다. 이때 목표는 전달받는 함수가 애초에 전달하는 함수가 받았던 것과 동일한 객체들을 받게 하는 것이다. 하지만 값 전달 방식의 매개변수로는 불가능하다. 매개변수는 원래 호출자가 넘겨준 인수의 복사본이기 때문이다. 그래서 범용적인 전달을 위해 참조 매개변수들을 사용해야 한다. 완벽 전달은 단순히 객체들을 전달하는 것 뿐만 아니라 그 객체의 특징과 형식(왼값/오른값 여부, const/volatile 여부)도 전달하는 것을 말한다. f라는 함수에 인수를 전달하는 함수를 만들어 보자. 전달 함수는 임의의 형식과 개수의 인수들을 받는 템플릿 이어야 하기 때문에 가변.. 2020. 7. 29.
C++11에서 이동 의미론이 항상 도움이 될까 결론부터 말하자면 아니다. 아마도 C++ 에서 가장 주된 기능은 이동 의미론일 것이다. 이로 인해 컴파일러는 비싼 복사 연산을 비교적 저렴한 이동 연산으로 대체할 수 있을 뿐 아니라 적절한 조건이 만족되면 반드시 대체해야 한다. 하지만 이동의미론을 지원하지 않는 형식들이 많고, 사용자 정의 형식들은 C++11에 완전히 맞게 수정되지 않았다면 컴파일러가 이동을 지원해도 응용 프로그램의 성능이 저절로 높아지지는 않는다. 이동을 명시적으로 지원하더라도 성능상의 이득이 크지 않을 수 있다. 컨테이너의 내용을 저렴하게 이동하는 방법이 없을 수도 있고, 컨테이너가 제공하는 저렴한 이동연산이 요구하는 까다로운 조건을 컨테이너 요소들이 만족하지 못하는 경우도 있을 수 있다. 그 예로 std::array가 있다. std.. 2020. 7. 28.
참조축약을 숙지하라 template void func(T&& param); Widget widgetFactory();// 오른값을 돌려주는 함수 Widget w;// 변수 (왼값) func(w);// func를 왼값 호출, T는 Widget&로 연역 func(widgetFactory());// func를 오른값 호출, T는 Widget으로 연역 두 func 모두 Widget이 전달되지만 Widget이 왼값인지 오른값인지에 따라 템플릿 매개변수 T에 대해 연역되는 형식이 다르다. 보편참조가 오른값/왼값 중 어느 값 참조가 될 것인지 결정한다. 그리고 이 메커니즘은 std::forward의 기본이 된다. 우선 C++에서 참조에 대한 참조는 위법이다. 하지만 보편 참조를 받는 함수 템플릿에 왼값을 넘겨주는 것은 컴파일이 된다. .. 2020. 7. 27.
보편참조에 대한 중복적재 대신 사용할 수 있는 기법들을 알아두라 2 보편참조를 받는 템플릿을 제한한다. std::enable_if는 컴파일러가 특정 템플릿을 존재하지 않는 것처럼 할 수 있다. 그런 템플릿을 비활성화된 템플릿이라고 한다. 기본적으로 모든 템플릿은 활성화 상태이지만 std::enable_if를 사용하는 경우, 특정 조건이 만족될 때에만 활성화된다. 일단 기존의 예제에 std::enable_if만 추가해보자 class Person{ public: template explicit Person(T&& n); ... }; // std::enable_if와 그 작동원리인 SFINAE는 나중에 따로 정리 여기서 우리가 지정하려고 하는 조건은 T가 Person이 아니라는 것이다. 이것을 판별할 유용한 형식특질로 두 형식이 같은지를 판별하는 std::is_same이 있다.. 2020. 7. 23.