0%

Tips about combination of unique_ptr and tuple

Problem

目前的主流就是以composition代替inheritance,因此可以寫出這樣的程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
struct SubCompoent1 {
int v = 100;
int add(int num) { return v + num; }
int sub(int num) { return v - num; }
};
struct SubCompoent2 {
int v = 300;
int mul(int num) { return v * num; }
int div(int num) { return v / num; }
};
struct Component {
Component() : comp1(new SubCompoent1), comp2(new SubCompoent2) {}
std::unique_ptr<SubCompoent1> comp1;
std::unique_ptr<SubCompoent2> comp2;
int add(int num) { return comp1->add(num); }
int sub(int num) { return comp1->sub(num); }
int mul(int num) { return comp2->mul(num); }
int div(int num) { return comp2->div(num); }
};
int func(Component *comp)
{
return comp->add(300);
}
int func1(Component *comp)
{
return comp->div(5);
}

這樣的程式碼很值觀,>不過問題也很明顯,一旦新增一個Function Call,接著又要改個地方

Possible Solution 1

將SubCompent的介面公開,然後提供一組介面存取SubComponent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct Component {
Component() : comp1(new SubCompoent1), comp2(new SubCompoent2) {}
std::unique_ptr<SubCompoent1> comp1;
std::unique_ptr<SubCompoent2> comp2;
SubCompoent1* getComp1() { return comp1.get(); }
const std::unique_ptr<SubCompoent2>& getComp2() { return comp2; }
};
nt func(Component *comp)
{
SubCompoent1* comp1 = comp->getComp1();
return comp1->add(300);
}
int func1(Component *comp)
{
const auto& comp2 = comp->getComp2();
return comp2->div(5);
}

跟上面方式相比,少了每次新增API介面就要修改Component的煩惱,不過要為每組Subcomponent提供一組Access Function,試著將他自動化

Possible Solution 2

結合C++14的get和tuple之後,可以寫成這樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct Component {
Component() : comp1(new SubCompoent1), comp2(new SubCompoent2) {}
std::unique_ptr<SubCompoent1> comp1;
std::unique_ptr<SubCompoent2> comp2;
SubCompoent1* getComp1() { return comp1.get(); }
const std::unique_ptr<SubCompoent2>& getComp2() { return comp2; }
};
int func(Component *comp)
{
return comp->get<SubCompoent1>()->add(300);
}
int func1(Component *comp)
{
return comp->get<SubCompoent2>()->div(5);
}

不過這樣還是需要輸出SubComponent的介面,在某些場合底下還是不太適用
不知道未來可不可以靠refelection和overload operator-> 來寫出更好的程式碼