Ruby의 모듈


(바보털) #1
#include <iostream>
#include <algorithm>
#include <string>

//이름만 있으면 예의바르게 만들어줍니다.
template< typename T >
struct Polite
{
      //타입 캐스팅하는게 중요.
      void self_introduce()
      {
            std::cout << "Hi! I'm " << ((T&)*this).name << "!\n";
      }
};

//출력할 수만 있으면 정사각형으로 출력할 수 있게 해줍니다
template< typename T >
struct SquarePrint
{
      void sqprint()
      {
            for(int i = 0; i < 3; ++i)
            {
                  for(int j = 0; j < 3; ++j)
                  {
                        std::cout << ((T&)*this) << ' ';
                  }

                  std::cout << '\n';
            }
      }
};

struct People: Polite< People >, SquarePrint< People >
{
      //이름이 있으니까 인사할 수 있습니다.
      std::string name;

      People(std::string namename): name(namename) {}

      //출력할 수 있으니까 정사각형으로 출력할 수 있습니다.
      friend std::ostream& operator<<(std::ostream& lhs, People& rhs)
      {
            lhs << rhs.name[ 0 ];

            return lhs;
      }
};

//반복할 수 있다면 여러 가지를 할 수 있게 해줍니다.
template< typename T >
struct Iterable
{
      //출력도 할 수 있고
      friend std::ostream& operator<<(std::ostream& lhs, Iterable& rhs)
      {
            lhs << '[';

            //범위기반 for문은 begin, end, ++, !=만 구현해주면 사용 가능합니다.
            for(auto i: (T&)rhs)
            {
                  lhs << i << ' ';
            }

            lhs << "\b]";

            return lhs;
      }

      //귀찮으니까 구현은 라이브러리에 맡깁니다.
      template< typename F >
      auto min_element(F comp)
      {
            return std::min_element(((T&)*this).begin(), ((T&)*this).end(), comp);
      }

      template< typename F >
      auto max_element(F comp)
      {
            return std::max_element(((T&)*this).begin(), ((T&)*this).end(), comp);
      }
};

struct Array5: Iterable< Array5 >
{
      //반복자 새로 만들기 귀찮으니까 포인터 그대로 씁시다.
      using iterator = int*;

      int arr[ 5 ] = { 0 };

      iterator begin()
      {
            return arr;
      }

      iterator end()
      {
            return arr + 5;
      }
};

int main()
{
      People minori("Minori");

      minori.self_introduce();
      minori.sqprint();

      Array5 a1;

      a1.arr[ 0 ] = 3;
      a1.arr[ 1 ] = 1;
      a1.arr[ 2 ] = 5;
      a1.arr[ 3 ] = 2;
      a1.arr[ 4 ] = 4;

      std::cout << a1 << '\n';

      std::cout << *a1.min_element([](auto lhs, auto rhs){ return lhs < rhs; }) << '\n';
      std::cout << *a1.max_element([](auto lhs, auto rhs){ return lhs < rhs; }) << '\n';

      return 0;
}

을 C++에서…

Ruby에서 모듈은 '이런이런 것들을 구현하고 날 포함하면 넌 이것들을 쓸 수 있어!'라는 느낌으로 쓰이는데, C++에서는 딱히 많이 쓰이지 않는 것 같아 대충 흉내내 보았습니다. 사실 C++에도 iterator_tag같은게 있기는 합니다만, 그건 그냥 껍데기라…

Concept 나오면 같이 섞어서 떡을 칠 수 있지 않을까, 기대를 해봅니다.

C++도 원시 자료형들 Boxing해서 쓸 수 있게 해주면 좋을텐데(int 상속해서 여차저차)…


(바보털) #2

'상속’이라는 단어가 어울리지 않는 때가 있습니다. Class의 상속은 말 그대로 포함 관계를 말하지만, 모듈을 가져오는 것은 기능을 추가하는 느낌입니다.

C++도 클래스가 열려있으면 진짜 재밌는 언어가 될텐데…