ð TOP / èªè§£æŒç¿ Step 7
ã³ãŒãèªè§£æŒç¿ Step 7ãåããºã«éèãïŒé£è§£ãã³ãã¬ãŒãïŒã¡ã¿ããã°ã©ãã³ã°ã®è§£èªè¡
STLããªãŒãã³ãœãŒã¹ã«æœã SFINAEã»enable_ifã»type_traitsã»Concepts ã®æå·ãè§£èªããæ¬æ¥ã®ã·ã°ããã£ã埩å
ãã
ãªãŒãã³ãœãŒã¹ã®ã©ã€ãã©ãªïŒnlohmann/json, Boost, EigenïŒãSTLã®ããããã¡ã€ã«ãéããç¬éãç»é¢ãåãå°œãã `template <typename T, typename std::enable_if<...>::type...>` ãšããæå·ã«å§åãããããšã¯ãããŸãããïŒã³ã³ãã€ã©ã«ãç¹å®ã®åã ãã«é¢æ°ãé©çšããããããã®é«åºŠãªåå¶çŽæè¡ïŒSFINAEïŒãšãC++20ã® Concepts ã«ããã¢ãã³èšæ³ã培åºè§£åããçããã®ç®ããæ³ãã§è£
食ãå¥ãåããæ°åè¡ã®ãšã©ãŒã¡ãã»ãŒãžã®çç¯äººã1ç§ã§èŠæãããã®éèçŒã逿ããŸãã
7.1 ãªããã³ãã¬ãŒãã³ãŒãã¯ãæå·ãã«èŠããã®ãïŒãSFINAEãšåå¶çŽã®ã¡ã«ããºã ã
ãã³ãã¬ãŒãã¯å®è¡æã§ã¯ãªããã³ã³ãã€ã«æã«åãå¥èšèªïŒã¡ã¿èšèªïŒãã§ãããªããããªå¥æªãªæ§æãå¿
èŠãªã®ãããã®æ ¹æ¬çç±ããçŽè§£ããŸãã
ð§ ãã³ã®ã³å
茩
ã·ãã¯ãå
çïŒå
茩ãããçŸå Žã§äœ¿ã£ãŠãOSSã®ã·ãªã¢ã©ã€ã¶ãããïŒSerializer.hppïŒãèªãã§èªäœã¯ã©ã¹ã察å¿ãããŠãã£ãŠèšããããã§ããã©ãéããŠã¿ããåªæã䞊ãã§ãŠäœã²ãšã€èªããŸããïŒ
`template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>` ãšããæ¬æ¥ã®é¢æ°åãåŒæ°ã¯äžäœã©ãã«ãããã§ããïŒïŒ
ð»ââïž ã·ãã¯ãå
ç
ã¬ããïŒå
šC++ããã°ã©ããäžåºŠã¯éãããã³ãã¬ãŒãã®æŽç€ŒããããªïŒ
åå¿è
ããã³ãã¬ãŒããèªããªãæå€§ã®çç±ã¯ã**ã颿°æ¬æ¥ã®ä»äºã** ãš **ãã³ã³ãã€ã©ãžã®åå¶çŽïŒéçªïŒã** ãåãè¡ã«ãã¡ãæ··ãã«æžãããŠããããããã
ð§ ãã³ã®ã³å
茩
ã³ã³ãã€ã©ãžã®éçªâŠâŠïŒæ®éã®é¢æ°ãªãŒããŒããŒããããã¡ãªãã§ããïŒ
ð»ââïž ã·ãã¯ãå
ç
ãã質åããïŒãæŽæ°åïŒint, short, uint32_t çïŒãªãmemcpyã§äžæ°ã«æžã蟌ã¿ããããæµ®åå°æ°ç¹åãªããšã³ãã£ã¢ã³å転ãããããã¯ã©ã¹ãªãserialize()ã¡ãœãããåŒã³ããããšããæãåããšã«äœååã颿°ãææžãããã®ã¯å°çãããïŒ
ããã解決ããã®ããSFINAEïŒã¹ãã£ãïŒçœ®æå€±æã¯ãšã©ãŒã«ãããïŒããšãããã³ã³ãã€ã«æã«åãèªåéžå¥ããç¥æ¥ãªããããïŒ
### SFINAEïŒã¹ãã£ãïŒãšã¯äœãïŒ **SFINAE** 㯠**Substitution Failure Is Not An Error**ïŒä»£å
¥å€±æã¯ã³ã³ãã€ã«ãšã©ãŒã«ãããïŒã®é æåããšã£ãC++ã®äžæ žã«ãŒã«ã§ãã éåžžãC++ã§äžæ£ãªåæäœïŒååšããªãã¡ã³ããžã®ã¢ã¯ã»ã¹ããç¡å¹ãªå倿ïŒãæžããšå³åº§ã«ã³ã³ãã€ã«ãšã©ãŒã«ãªããŸãã ãããã**ãã³ãã¬ãŒãå®äœåã®åè£éžå®äž** ã«éã£ãŠã¯ïŒ > **ããã®å T ã§ãã³ãã¬ãŒããå±éããããšããã倱æããïŒ ããããšã©ãŒã«ããã®ã§ã¯ãªããåè£ãªã¹ãããéãã«é€å€ïŒè±èœïŒãããŠã次ã®ãªãŒããŒããŒã颿°ãæ¢ããïŒã** ãšããç¹å¥ãªæ©èµŠãäžããããŸãã ã©ã€ãã©ãªã®äœè
ã¯ãã®ã«ãŒã«ãéæã«åãã`std::enable_if` ã䜿ã£ãŠãæ¡ä»¶ãæºãããªãåããããšè±èœãããïŒïŒé©åããåã ãã«é¢æ°ãåŒã³åºãããïŒããšããé«åºŠãªåããºã«ãçµãã§ããã®ã§ãã
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
ãã³ãã¬ãŒãã¯ãå®è¡æãã§ã¯ãªããã³ã³ãã€ã«æã®äº€éæŽçã : 奿ªãªã³ãŒãã®9å²ã¯å®è¡æã®åŠçã§ã¯ãªãããã©ã®åããã®é¢æ°ã«éããã©ã®åã匟ããããšããéçªïŒåå¶çŽïŒã®èšè¿°ã§ãã
7.2 ãã³ãã¬ãŒãèªè§£ã®æ¥µæïŒ3段éãçããã®ç®ããæ³ïŒOnion Peeling MethodïŒã
æå·ã«èŠãããã³ãã¬ãŒãããå€åŽã®ç®ã1æãã€å¥ããã°ãäžèº«ã¯é©ãã»ã©å¹³å¡ãªããã€ãã®é¢æ°ãã§ãã
### ãããå®è·µãããçããã®ç®ããæ³ã 以äžã®æå·ã®ãããªé¢æ°ã·ã°ããã£ãäŸã«ãèªè§£ã®ã¹ãããã远ã£ãŠã¿ãŸãããã ```cpp // ð± åå¿è
ãçµ¶æããæå·ã³ãŒã template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> void writeToBuffer(PacketBuffer& buf, T value); ``` #### ã第1å±€ã®ç®ãããïŒéçªïŒSFINAEè£
食ïŒãæã§é ãïŒ æåãããã¹ãŠãèªãã§ã¯ãããŸããã`template <...>` ã®äžã®åå¶çŽãäžæŠæã§é ããŸãïŒ ```cpp // ð ç®ãå¥ããšâŠãã ã®ã颿°åããåŒæ°ããæ»ãå€ããçŸããïŒ void writeToBuffer(PacketBuffer& buf, T value); ``` - **æ»ãå€**: `void` - **颿°å**: `writeToBuffer` - **åŒæ°**: `buf` ãš `T value` ããã ãã§ãããããã±ãããããã¡ã«äœãã®å€ `value` ãæžã蟌ã颿°ãªãã ãªããšæ¥åäžã®ç®çãç¬æã«ææ¡ã§ããŸãã --- #### ã第2å±€ã®ç®ãããïŒåç¹æ§ïŒtype_traitsïŒã®æ¡ä»¶ãæ¥æ¬èªåããïŒ é ããŠããéçªã®éšåãåãåºããäœãå€å®ãããŠãããã翻蚳ããŸãïŒ ```cpp std::enable_if<std::is_integral<T>::value, int>::type = 0 ``` - `std::is_integral<T>::value` â **ãT ã¯æŽæ°åïŒint, char, uint64_tçïŒãïŒã** - `std::enable_if<æ¡ä»¶, å>::type` â **ãããæ¡ä»¶ãçïŒtrueïŒãªãããã®åãæå¹åããã** ã€ãŸãããã®éçªãèšã£ãŠããããšã¯ããã£ãããã ãã§ãïŒ > **ãT ãæŽæ°åã®å Žåã®ã¿ããã® writeToBuffer 颿°ãéããŸããã** --- #### ã第3å±€ã®ç®ãããïŒå
·è±¡åã代å
¥ããŠã·ãã¥ã¬ãŒã·ã§ã³ããïŒ ããåŒã³åºãå
ã `writeToBuffer(buf, 42);`ïŒ42 㯠intïŒãªãïŒ - `is_integral<int>::value` 㯠`true` â ãã®é¢æ°ãçãæ®ããæ£åžžã«åŒã°ããïŒ ãã `writeToBuffer(buf, 3.14f);`ïŒfloatïŒãªãïŒ - `is_integral<float>::value` 㯠`false` â `enable_if` ã®äžã« `type` ãååšãã代å
¥å€±æïŒ - **SFINAEçºåïŒ** ãšã©ãŒã«ã¯ãªãããæµ®åå°æ°ç¹çšã®å¥ã® `writeToBuffer` ãžã«ãŒãã£ã³ã°ãããïŒ
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
ã颿°ã·ã°ããã£ã®æ¬äœããšãéçªããèŠèŠçã«åé¢ãã : ãŸãæ»ãå€ã»é¢æ°åã»åŒæ°ã ããæŸãèªã¿ããŠé¢æ°ã®è²¬åãææ¡ãããã®åŸã«ãã³ãã¬ãŒãåŒæ°éšã®æ¡ä»¶ïŒtype_traitsïŒããã§ãã¯ããã®ãæçã®èªè§£ã«ãŒãã§ãã
7.3 æŒç¿ã³ãŒãïŒçŸå Žã®æ±çšã²ãŒã ãã±ããã·ãªã¢ã©ã€ã¶ïŒSFINAE vs ConceptsçïŒ
å€å
žC++11ã® enable_if çãšãã¢ãã³C++20ã® Concepts çãæ¯èŒå¯Ÿæ¯ãåããºã«ãçŸä»£ã©ã®ããã«åçã«é²åã»èªã¿ããããªã£ãããäœæããŸãã
ð PacketSerializer.hpp
#include <iostream>
#include <vector>
#include <string>
#include <type_traits>
#include <cstring>
#include <cstdint>
// ç°¡æãã±ãããããã¡
class PacketBuffer {
public:
std::vector<uint8_t> data;
void writeRaw(const void* src, size_t size) {
const uint8_t* bytePtr = static_cast<const uint8_t*>(src);
data.insert(data.end(), bytePtr, bytePtr + size);
}
};
// ============================================================================
// ðïž å€å
žC++11/14ã¹ã¿ã€ã«ïŒstd::enable_if ãçšããSFINAEåéžå¥
// ============================================================================
namespace ClassicSerializer {
// ãã±ãŒã¹1ïŒæŽæ°åïŒint, short, uint32_t çïŒã
// memcpy ã«ãããã€ãåãã€ã¬ã¯ãæžã蟌ã¿
template <typename T,
typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
void write(PacketBuffer& buf, T val) {
std::cout << "[SFINAE: æŽæ°å] ãµã€ãº " << sizeof(T) << " ãã€ããçŽæ¥æžã蟌ã¿: " << val << "\n";
buf.writeRaw(&val, sizeof(T));
}
// ãã±ãŒã¹2ïŒæµ®åå°æ°ç¹åïŒfloat, double çïŒã
template <typename T,
typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
void write(PacketBuffer& buf, T val) {
std::cout << "[SFINAE: æµ®åå°æ°ç¹å] 粟床ãä¿è·ããŠæžã蟌ã¿: " << val << "\n";
buf.writeRaw(&val, sizeof(T));
}
// ãã±ãŒã¹3ïŒæååïŒstd::stringïŒã
// é·ãïŒuint32_tïŒïŒ æåå®äœã®é ã«æžã蟌ã
template <typename T,
typename std::enable_if<std::is_same<T, std::string>::value, int>::type = 0>
void write(PacketBuffer& buf, const T& val) {
std::cout << "[SFINAE: æååå] é·ã " << val.size() << " + æå忬äœãæžã蟌ã¿: " << val << "\n";
uint32_t len = static_cast<uint32_t>(val.size());
buf.writeRaw(&len, sizeof(len));
buf.writeRaw(val.data(), len);
}
}
// ============================================================================
// ð ã¢ãã³C++20ã¹ã¿ã€ã«ïŒConceptsïŒã³ã³ã»ããïŒãš requiresç¯ã«ããæå¿«ãªèšè¿°
// ============================================================================
#if __cplusplus >= 202002L || defined(_MSVC_LANG) && _MSVC_LANG >= 202002L
#include <concepts>
namespace ModernSerializer {
// æŽæ°åã³ã³ã»ãã
template <typename T>
concept NetworkInteger = std::integral<T>;
// æµ®åå°æ°ç¹ã³ã³ã»ãã
template <typename T>
concept NetworkFloat = std::floating_point<T>;
// èªäœã¯ã©ã¹ã serialize() ã¡ãœãããæã£ãŠããããæ€èšŒããã³ã³ã»ããïŒ
template <typename T>
concept CustomSerializable = requires(T a, PacketBuffer& buf) {
{ a.serialize(buf) } -> std::same_as<void>;
};
// 1. æŽæ°ã®æžã蟌ã¿ïŒè±èªã®æç« ã®ããã«èªããïŒïŒ
void write(PacketBuffer& buf, NetworkInteger auto val) {
std::cout << "[Concepts: æŽæ°å] " << val << "\n";
buf.writeRaw(&val, sizeof(val));
}
// 2. æµ®åå°æ°ç¹ã®æžã蟌ã¿
void write(PacketBuffer& buf, NetworkFloat auto val) {
std::cout << "[Concepts: æµ®åå°æ°ç¹å] " << val << "\n";
buf.writeRaw(&val, sizeof(val));
}
// 3. èªäœã«ã¹ã¿ã ãªããžã§ã¯ãã®æžã蟌ã¿ïŒã¡ã³ã颿° serialize ãèªååŒã³åºãïŒ
template <CustomSerializable T>
void write(PacketBuffer& buf, const T& obj) {
std::cout << "[Concepts: ã«ã¹ã¿ã ãªããžã§ã¯ã] å
éšserializeãåŒã³åºã\n";
obj.serialize(buf);
}
}
#endif // C++20
7.4 ã³ã³ãã€ã«ãšã©ãŒæªç£ã®éæ²»æ³ïŒ100è¡ã®ãšã©ãŒãããæåã®1è¡ããç¹å®ãã
ãã³ãã¬ãŒãã®ã³ã³ãã€ã«ãšã©ãŒã¯ãªããããªã«é·å€§ãªã®ãïŒãããã¯ã«ãªããã«æ žå¿ãçªããããã°ã®äœæ³ãåŠã³ãŸãã
### ãã³ãã¬ãŒããšã©ãŒãèªãããã®ãèŠç·èªå°ã ãã³ãã¬ãŒãã®ãšã©ãŒãåºããšããã³ã³ãœãŒã«ã«ã¯100è¡ã200è¡ã®ãã°ãäžç¬ã§æµããŠãããŸãã ãã®ãšãåå¿è
㯠**ãäžçªäžã«ã¹ã¯ããŒã«ããŠæåŸã®è¡ãèªãããšããã** ãããæ··ä¹±ããŠèªçããŸãã #### éåïŒäžçªäžãŸã§æ»ãããerror: no matching functionãã®çŽåŸãèŠãïŒ ``` // â ç»é¢äžéšã«äžŠã¶æ°åè¡ã®ãã°ïŒããã¯åãªããåè£ããèœã¡ãçç±ã®èšãèš³ãªã¹ããã«éããªãïŒ note: candidate template ignored: requirement 'std::is_integral<Player>::value' was not satisfied note: candidate template ignored: requirement 'std::is_floating_point<Player>::value' was not satisfied ... // â äžçªäžã«ãããæåã®çå®ããèŠãïŒ error: no matching function for call to 'write(PacketBuffer&, Player&)' note: candidate template ignored: constraints not satisfied [with T = Player] ``` 1. **第1ççŒç¹ïŒæäžéšïŒ**: - `no matching function for call to 'write(buf, player)'` - â **ãã©ã®é¢æ°ããã©ããªåã®åŒæ°ã§åŒãŒããšããŠå€±æãããïŒã** ãäžçºã§åãããŸãã 2. **第2ççŒç¹ïŒçŽäžã® noteïŒ**: - `candidate template ignored: requirement '...' was not satisfied` - â ã³ã³ãã€ã©ãããã®é¢æ°ãåœãŠã¯ããããšããããåå¶çŽïŒéçªïŒã«åŒã£ããã£ãŠè±èœãããããšæããŠãããŠããŸãã 3. **解決çã®ç¹å®**: - åŒæ°ã«æž¡ãã `Player` ã¯æŽæ°ã§ãæµ®åå°æ°ç¹ã§ãæååã§ããªããããå
šãªãŒããŒããŒãããè±èœããããšã倿ããŸãã - â 察çïŒãPlayer çšã®ã·ãªã¢ã©ã€ãºãªãŒããŒããŒããæ°èšãããããPlayer ã« serialize() ã¡ãœãããçãããã®ã©ã¡ãããå¿
èŠã ãšç¢ºå®ã§ããŸãïŒ
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
ãã³ãã¬ãŒããšã©ãŒã¯ãäžãã§ã¯ãªããæäžéšããèŠã : äžéšã«äžŠã¶å€§éã®ãã°ã¯ãåè£ããå€ããçç±ã®èšãèš³ãã§ããäžçªäžã«ãããåŒã³åºãããšãã颿°åãšæž¡ãããåããããå
šãŠã®æ ¹æ¬åå ã§ãã
ð ç解床ãã§ãã¯ã¯ã€ãº
Q1. 以äžã®ãã³ãã¬ãŒã宣èšã«ãããŠããã®é¢æ°æ¬æ¥ã®ãæ»ãå€åïŒReturn TypeïŒãã¯ã©ãã§ãããïŒ
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type
calculateBonus(T level);
1. void 2. double 3. int 4. std::is_integral<T>
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒdouble
æ£è§£ã§ãïŒãstd::enable_if<æ¡ä»¶, å>::typeãã®ç¬¬2åŒæ°ã«æå®ãããåïŒãã®å Žå㯠doubleïŒããæ¡ä»¶ãæºããããšãã«æ¬æ¥ã®æ»ãå€åãšããŠå®äœåãããŸãããçããã®ç®ããæ³ãã§å€åŽã®è£
食ãå¥ãããšãæ»ãå€ã double ã§ããããšãèŠæããŸãã
Q2. C++ã®èšèªä»æ§ãSFINAEïŒSubstitution Failure Is Not An ErrorïŒãã®æåãšããŠæ£ãã説æã¯ã©ãã§ãããïŒ
1. ãã³ãã¬ãŒãåŒæ°ã®ä»£å
¥æã«ãšã©ãŒãçºçããå Žåãå³åº§ã«ã³ã³ãã€ã«ã忢ããŠãšã©ãŒãã°ãåºåãã 2. ãã³ãã¬ãŒãåŒæ°ã®ä»£å
¥ã«å€±æãã颿°ã¯ãã³ã³ãã€ã«ãšã©ãŒã«ããããªãŒããŒããŒãã®åè£ãªã¹ãããéãã«é€å€ããããä»ã®åè£é¢æ°ãæ¢çŽ¢ããã 3. å®è¡æã« try-catch ã§äŸå€ãææããŠå®å
šã«åé¿ããä»çµã¿ã®ããš 4. ã¡ã¢ãªãªãŒã¯ãèªåæ€åºããŠè§£æŸããã¬ããŒãžã³ã¬ã¯ã¿ã®æ©èœã®ããš
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒãã³ãã¬ãŒãåŒæ°ã®ä»£å
¥ã«å€±æãã颿°ã¯ãã³ã³ãã€ã«ãšã©ãŒã«ããããªãŒããŒããŒãã®åè£ãªã¹ãããéãã«é€å€ããããä»ã®åè£é¢æ°ãæ¢çŽ¢ããã
æ£è§£ã§ãïŒSFINAEã®æ¬è³ªã¯ã代å
¥å€±æã¯ãšã©ãŒã«ããããã§ããæ¡ä»¶ãæºãããªããã³ãã¬ãŒãã¯åã«åè£ããè±èœããã ãã§ãšã©ãŒã«ãªããªããããæ¡ä»¶ããšã«è€æ°ã®ãã³ãã¬ãŒããå®å
šã«åºãåããããšãã§ããŸãã
Q3. ãã³ãã¬ãŒã颿°ãåŒã³åºããéã«100è¡ãè¶
ããé·å€§ãªã³ã³ãã€ã«ãšã©ãŒãåºåãããŸãããããã®éçºè
ãæåã«åãã¹ãèŠç·èªå°ã¯ã©ãã§ãããïŒ
1. ã³ã³ãœãŒã«ã®äžçªäžãŸã§ã¹ã¯ããŒã«ããŠãæåŸã®è¡ã®ãšã©ãŒã¡ãã»ãŒãžãèªã 2. ã³ã³ãœãŒã«ãäžçªäžãŸã§ã¹ã¯ããŒã«ããæåã®ãerror: no matching function for call to ...ããšæž¡ãããåŒæ°ã®åã確èªãã 3. ãšãããã clean ãã«ããããŠããäžåºŠã³ã³ãã€ã«ããŠã¿ã 4. C++ã®ã³ã³ãã€ã©ãåã€ã³ã¹ããŒã«ãã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒã³ã³ãœãŒã«ãäžçªäžãŸã§ã¹ã¯ããŒã«ããæåã®ãerror: no matching function for call to ...ããšæž¡ãããåŒæ°ã®åã確èªãã
æ£è§£ã§ãïŒãã³ãã¬ãŒããšã©ãŒã®äžéšã«äžŠã¶å€§éã®ãã°ã¯ãåè£ããè±èœããçç±ïŒèšãèš³ïŒãã®çŸ
åã§ããäžçªäžã«ãããã©ã®é¢æ°ããã©ã®åã§åŒã³åºãããšããã®ããã確èªããã®ãæç解決ã®éåã§ãã
Q4. å€å
žC++ã®ãstd::enable_ifãã«ããåå¶çŽãšæ¯èŒããŠãã¢ãã³C++20ã®ãConceptsïŒã³ã³ã»ããïŒ/ requiresç¯ããæ¡çšããæå€§ã®å©ç¹ã¯äœã§ãããïŒ
1. å®è¡é床ã100åé«éã«ãªã 2. æå·ã®ãããªãã¯ããenable_ifã®ãã¹ããäžèŠã«ãªããå¹³æãªè±èªæ§æã§åå¶çŽãèšè¿°ã§ãããšã©ãŒã¡ãã»ãŒãžã極ããŠæå¿«ã«ãªã 3. ãã³ãã¬ãŒãã䜿ããã«åçããªã¢ãŒãã£ãºã ïŒvirtualïŒã«èªå倿ããã 4. ããããã¡ã€ã«ãäžå include ããªããŠãåãããã«ãªã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒæå·ã®ãããªãã¯ããenable_ifã®ãã¹ããäžèŠã«ãªããå¹³æãªè±èªæ§æã§åå¶çŽãèšè¿°ã§ãããšã©ãŒã¡ãã»ãŒãžã極ããŠæå¿«ã«ãªã
æ£è§£ã§ãïŒConcepts ã¯SFINAEã®è€éæªå¥ãªããã¯ãéå»ã®ãã®ã«ããããã«C++20ã§å°å
¥ãããæé«å³°ã®èšèªæ©èœã§ããã³ãŒããèªã¿ããããªãã ãã§ãªããã³ã³ãã€ã©ããã©ã®ã³ã³ã»ãããæºãããŠããªãããã1è¡ã§æå¿«ã«å ±åããŠãããããã«ãªããŸãã
ð»ââïž ã·ãã¯ãC++ã©ã ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ã·ã¹ãã
ãã©ãŠã¶ã§JavaScriptãæå¹ã«ãããšããã©ãŠã¶å
ã€ã³ããŒããŒã²ãŒã ãšãã¥ã¬ãŒã¿ãã¡ã¢ãªãããå¯èŠåãUMLã¯ã©ã¹å³ã察話å解説ãç解床ã¯ã€ãºãèµ·åããŸãã
ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ãéå§ãã â