조건에 따라 리턴타입이 다른 함수 만들기?

jinserk의 이미지

예를 들어서,

template <typename T>
class A {
   A<T>* t1_ptr;
   T*    t2_ptr;
   bool flag;
 
public:
 
   (T1& or T2&) operator[](int idx) {
       if (flag)
           return t1_ptr[idx];
       else
           return t2_ptr[idx];
   }

위와 같은 클래스가 있다고 할때요.
멤버함수의 리턴 타입을 내부 조건에 따라 다르게 주어야 할 필요가 생겼습니다.
operator[] 가 unitary parameter 라서 function overriding 도 못할 듯 싶구요.
뭔가 좋은 꽁수가 없을까요?

sev314의 이미지

복합체 패턴(composite pattern)을 써봤습니다.

그런데 제가 코드의 의도를 잘 파악했는지 모르겠습니다.

이런 걸 의도하신 것 맞습니까?

#include <iostream>
#include <utility>
#include <memory>
#include <vector>
 
using namespace std;
 
template <typename T>
class A {
    private:
        vector< A<T> > *t1;
        T *t2;
        bool flag;
 
    public:
        A<T> &operator[](int idx) { return t1->at(idx); }
 
        A(bool flag = false) : flag(flag) {
            if (flag)
            {
                t1 = new vector< A<T> >();
                t2 = 0;
            }
            else
            {
                t1 = 0;
                t2 = new T();
            }
        }
        ~A() {
        }
 
        bool is_vec() const { return flag; }
 
        operator T() const { return *t2; }
 
        A<T>& operator =(const T& rhs) {
            (*t2) = rhs;
            return *this;
        }
 
        A<T>& operator =(const A<T>& rhs) {
            A<T>& lhs = *this;
 
            if (rhs.t1)
                lhs.t1   = new vector< A<T> >(*(rhs.t1));
            if (rhs.t2)
                lhs.t2   = new T(*(rhs.t2));
            lhs.flag = rhs.flag;
 
            return lhs;
        }
 
        size_t size() const {
            return t1->size();
        }
 
        void resize(size_t size) {
            t1->resize(size);
        }
};
 
int main()
{
    A<int> l1(false);
    A<int> l2(false);
    A<int> l3(false);
    A<int> l4(false);
    A<int> l5(false);
    A<int> c1(true);
    A<int> c2(true);
 
    l1 = 71;
    l2 = 10;
    l3 = 9;
    l4 = 17;
    l5 = 20;
 
    c1.resize(3);
    c1[0] = l1;
    c1[1] = l2;
    c1[2] = l3;
 
    c2.resize(3);
    c2[0] = l4;
    c2[1] = l5;
    c2[2] = c1;
 
    cout << c2[0] << endl;
    cout << c2[1] << endl;
    cout << c2[2][0] << endl;
    cout << c2[2][1] << endl;
    cout << c2[2][2] << endl;
 
    return 0;
}
 
// EOF

jinserk의 이미지

직접 코딩까지 해주시니 정말 감사드립니다.

원래 의도는 아래와 같은 코드였습니다.

template <typename T>
class A
{
    private:
        A<T>* pcontainer_;
        T*    pelement_;
        bool  is_container_;
 
    public:
        A(int s1) {
            set(s1);
        }
 
        A(int s1, int s2) {
            set(s1, s2);
        }
 
        void set(int s1) {
            is_container_ = false;
            pcontainer_ = NULL;
            pelement_ = new T [s1];
        }
 
        void set(int s1, int s2) {
            is_container_ = true;
            pcontainer_ = new A<T> [s1];
            pelement_ = NULL;
 
            for (int i = 0; i < s1; i++)
                pcontainer_[i].set(s2);
        }
 
        (????) operator[] (int idx) {
            if (is_container_)
                return pcontainer_[idx];
            else
                return pelement_[idx];
         }
 
};

올려주신 코드와 제 의도한 코드를 놓고 비교해보니,
저는 A 의 하위를 1차원 벡터로 생각했던 것에 비해
올려주신 코드는 하위를 원소 하나하나로 생각하는데 차이가 있는 듯 합니다.
생각해보니 캐스트연산자를 적절히 쓰면 될것도 같네요.
좋은 힌트를 주셔서 정말 감사합니다.

Leo.