C++ - 자주 사용하는 C++ 이디엄(idiom) Extension Member Function
C#의 확장 메소드와 같이 기존 클래스에 대해서 멤버 함수의 확장을 operator 오버로드를 구사하여 시뮬레이트 하는 idiom 이다.
예컨대 std::vector에 print 라는 모든 요소를 출력하는 확장 구성원을 만들려고 한다면
const struct Listed_print{
using result_type=void;
template<class Range>
void operator()(const Range& r)
{
std::copy(r.cbegin(),r.cend(),std::experimental::make_ostream_joiner(std::cout,","));
}
}listed_print={};
template<class Range,class F>
typename std::result_of<F(Range&)>::type operator|(const Range& r,F function)
{
return function(r);
}
int main()
{
std::vector<int> v{1,2,3,4,5};
v | listed_print;
}
반환 값이 필요한 경우 시그너처에서 argument 부분을 추출하여 result_of메타 함수로 반환 타입을 빼낸다.
const struct Listed_print{
template<class Range>
const Range& operator()(const Range& r)const
{
std::copy(r.cbegin(),r.cend(),std::experimental::make_ostream_joiner(std::cout,","));
std::cout<<std::endl;
return r;
}
}listed_print={};
template<class Range,class F>
auto operator|(const Range& r,F function)
{
return function(r);
}
반복자를 만들 때 보다 효율적으로 조작이 가능하다.
static const auto reverse=[](auto& r){
std::reverse(r.begin(),r.end());
return r;
};
static const auto print=[](const auto& r){
std::copy(r.cbegin(),r.cend(),std::experimental::make_ostream_joiner(std::cout," "));
return r;
};
template<class Range,class Functor>
auto operator|(Range& r,const Functor& func)
{
return func(r);
}
int main()
{
std::vector<int> v{1,2,3,4,5};
v | reverse | print;
}
이 글은 2020-06-06에 작성되었습니다.