๐ ํ์ ํน์ฑ์ ์ด์ฉํ ์ ์ ์ด์ค์ : C++์ ๋ง๋ฒ ๊ฐ์ ๊ธฐ๋ฅ! ๐ฉ

์๋ ํ์ธ์, ์ฝ๋ฉ ๋ง๋ฒ์ฌ ์ฌ๋ฌ๋ถ! ์ค๋์ C++์ ํฅ๋ฏธ์ง์งํ ์ธ๊ณ๋ก ์ฌ๋ฌ๋ถ์ ์ด๋ํฉ๋๋ค. ํนํ 'ํ์ ํน์ฑ์ ์ด์ฉํ ์ ์ ์ด์ค์ '์ด๋ผ๋ ๊ฐ๋ ฅํ ๋ง๋ฒ ์ฃผ๋ฌธ์ ๋ํด ์์๋ณผ ๊ฑฐ์์. ์ด ์ฃผ๋ฌธ์ ์ฌ๋ฌ๋ถ์ ์ฝ๋๋ฅผ ๋์ฑ ์์ ํ๊ณ ํจ์จ์ ์ผ๋ก ๋ง๋ค์ด์ค ๊ฑฐ์์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ๋ถ์ ํ๋ก๊ทธ๋๋ฐ ์ค๋ ฅ์ ํ ๋จ๊ณ ์ ๊ทธ๋ ์ด๋ํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ ! ๐
๐ก ์๊ณ ๊ณ์ จ๋์? ํ์ ํน์ฑ(Type Traits)์ C++11๋ถํฐ ๋์ ๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ผ๋ก, ์ปดํ์ผ ์๊ฐ์ ํ์ ์ ๋ํ ์ ๋ณด๋ฅผ ์ป๊ฑฐ๋ ํ์ ์ ๋ณํํ ์ ์๊ฒ ํด์ค๋๋ค. ์ด๋ฅผ ์ด์ฉํ ์ ์ ์ด์ค์ ์ ์ฝ๋์ ์์ ์ฑ์ ํฌ๊ฒ ๋์ฌ์ค๋๋ค!
๐งโโ๏ธ ํ์ ํน์ฑ: ์ฝ๋์ ์์ ์งํด์ด
ํ์ ํน์ฑ์ ๋ง์น ์ฝ๋์ ์์ ์งํด์ด์ ๊ฐ์์. ์ฌ๋ฌ๋ถ์ด ์๋ํ ๋๋ก ์ฝ๋๊ฐ ์๋ํ๋์ง ์ปดํ์ผ ์๊ฐ์ ํ์ธํด์ฃผ์ฃ . ์ด๋ ๋ง์น ์ฌ๋ฅ๋ท์์ ์ ๋ฌธ๊ฐ๋ค์ด ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ๋ฅผ ๊ฒํ ํด์ฃผ๋ ๊ฒ๊ณผ ๋น์ทํฉ๋๋ค. ์ค์๋ฅผ ๋ฏธ๋ฆฌ ์ก์๋ด๊ณ , ๋ ๋์ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๊ฒ ๋์์ฃผ๋ ๊ฑฐ์ฃ ! ๐ก๏ธ
๐ ํ์ ํน์ฑ์ ๊ธฐ๋ณธ ๊ฐ๋
ํ์
ํน์ฑ์ <type_traits>
ํค๋์ ์ ์๋์ด ์์ต๋๋ค. ์ด๋ค์ ํ
ํ๋ฆฟ ๋ฉํํ๋ก๊ทธ๋๋ฐ์ ์ฌ์ฉํ์ฌ ํ์
์ ๋ํ ๋ค์ํ ์ ๋ณด๋ฅผ ์ ๊ณตํ๊ฑฐ๋, ํ์
์ ๋ณํํฉ๋๋ค.
- โ
std::is_integral
: ์ ์ ํ์ ์ธ์ง ํ์ธ - โ
std::is_floating_point
: ๋ถ๋์์์ ํ์ ์ธ์ง ํ์ธ - โ
std::is_array
: ๋ฐฐ์ด์ธ์ง ํ์ธ - โ
std::is_pointer
: ํฌ์ธํฐ์ธ์ง ํ์ธ - โ
std::remove_reference
: ์ฐธ์กฐ๋ฅผ ์ ๊ฑฐํ ํ์ ์ป๊ธฐ
์ด๋ฐ ํ์ ํน์ฑ๋ค์ ์ด์ฉํ๋ฉด, ์ปดํ์ผ ์๊ฐ์ ํ์ ์ ๋ํ ๋ค์ํ ๊ฒ์ฌ์ ๋ณํ์ ์ํํ ์ ์์ด์. ๋ง์น ์ฝ๋์ ๋ง๋ฒ์ ๋๋ณด๊ธฐ๋ฅผ ๋ค์ด๋๋ ๊ฒ๊ณผ ๊ฐ์ฃ ! ๐ฎ
๐ ๏ธ ์ ์ ์ด์ค์ : ์ปดํ์ผ ์๊ฐ์ ๋ง๋ฒ
์ ์ ์ด์ค์
์ static_assert
๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํํฉ๋๋ค. ์ด๋ ์ปดํ์ผ ์๊ฐ์ ์กฐ๊ฑด์ ๊ฒ์ฌํ๊ณ , ์กฐ๊ฑด์ด ๊ฑฐ์ง์ด๋ฉด ์ปดํ์ผ์ ์ค๋จ์ํค๋ ๊ฐ๋ ฅํ ๋๊ตฌ์์.
template <typename T>
void processNumber(T value) {
static_assert(std::is_arithmetic<T>::value, "Arithmetic type expected");
// ํจ์ ๋ด์ฉ...
}
์ด ์ฝ๋๋ processNumber
ํจ์์ ์ฐ์ ํ์
(์ ์ ๋๋ ๋ถ๋์์์ )๋ง ์ ๋ฌ๋๋๋ก ๋ณด์ฅํฉ๋๋ค. ๋ค๋ฅธ ํ์
์ด ์ ๋ฌ๋๋ฉด ์ปดํ์ผ๋ฌ๊ฐ ์น์ ํ๊ฒ ๊ฒฝ๊ณ ๋ฅผ ํด์ฃผ์ฃ . ๋ง์น ์ฌ๋ฅ๋ท์์ ์ ๋ฌธ๊ฐ๊ฐ ์ฌ๋ฌ๋ถ์ ์ฝ๋๋ฅผ ๋ฆฌ๋ทฐํด์ฃผ๋ ๊ฒ์ฒ๋ผ์! ๐จโ๐ป
๐ ํ: ์ ์ ์ด์ค์ ์ ์ฌ์ฉํ๋ฉด ๋ฐํ์ ์ค๋ฅ๋ฅผ ์ปดํ์ผ ์๊ฐ ์ค๋ฅ๋ก ์ ํํ ์ ์์ด์. ์ด๋ ๋ฒ๊ทธ๋ฅผ ๋ ๋นจ๋ฆฌ, ๋ ์ฝ๊ฒ ์ก์ ์ ์๊ฒ ํด์ค๋๋ค!
๐ญ ํ์ ํน์ฑ์ ๋ค์ํ ์ผ๊ตด๋ค
ํ์ ํน์ฑ์ ์ ๋ง ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ ๋ฌธ๊ฐ๋ค์ ๋ง๋ ์ ์๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ ! ๋ช ๊ฐ์ง ์ฌ๋ฏธ์๋ ์๋ฅผ ์ดํด๋ณผ๊น์?
๐ข ํ์ ๋ณํ์ ๋ง๋ฒ
std::conditional
์ ์ฌ์ฉํ๋ฉด ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ค๋ฅธ ํ์
์ ์ ํํ ์ ์์ด์. ์ด๊ฑด ๋ง์น ๋ง๋ฒ์ฌ๊ฐ ์ฃผ๋ฌธ์ ์ธ์ ๋ฌผ๊ฑด์ ๋ณํ์ํค๋ ๊ฒ๊ณผ ๋น์ทํด์!
template <bool Condition, typename T, typename F>
struct magical_type_selector {
using type = typename std::conditional<Condition, T, F>::type;
};
// ์ฌ์ฉ ์
using result = magical_type_selector<true, int, float>::type; // int ์ ํ
using another_result = magical_type_selector<false, int, float>::type; // float ์ ํ
์ด๋ ๊ฒ ํ๋ฉด ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ค๋ฅธ ํ์ ์ ์ ํํ ์ ์์ด์. ์ฝ๋๊ฐ ์ํฉ์ ๋ฐ๋ผ ๋๋ํ๊ฒ ์ ์ํ๋ ๊ฑฐ์ฃ ! ๐ง
๐ ํ์ ์ ๋ณด ํ์
std::is_same
์ ์ฌ์ฉํ๋ฉด ๋ ํ์
์ด ๊ฐ์์ง ๋น๊ตํ ์ ์์ด์. ์ด๊ฑด ๋ง์น ๋ ๋ง๋ฒ ๋ฌผ์ฝ์ด ๊ฐ์ ํจ๊ณผ๋ฅผ ๋ด๋์ง ํ์ธํ๋ ๊ฒ๊ณผ ๋น์ทํ์ฃ !
template <typename T, typename U>
void compare_types() {
if (std::is_same<T, U>::value) {
std::cout << "๋ ํ์
์ ๊ฐ์์!" << std::endl;
} else {
std::cout << "๋ ํ์
์ ๋ฌ๋ผ์!" << std::endl;
}
}
// ์ฌ์ฉ ์
compare_types<int, int>(); // "๋ ํ์
์ ๊ฐ์์!" ์ถ๋ ฅ
compare_types<int, float>(); // "๋ ํ์
์ ๋ฌ๋ผ์!" ์ถ๋ ฅ
์ด๋ฐ ์์ผ๋ก ํ์ ์ ๋น๊ตํ๋ฉด, ์ฝ๋์ ๋์์ ๋ ์ ํํ๊ฒ ์ ์ดํ ์ ์์ด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์ ๊ผญ ๋ง๋ ์ ๋ฌธ๊ฐ๋ฅผ ์ฐพ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ ! ๐ต๏ธโโ๏ธ
๐ก ์ฌ๋ฏธ์๋ ์ฌ์ค: ํ์ ํน์ฑ์ ์ด์ฉํ๋ฉด ์ปดํ์ผ ์๊ฐ์ ๋ณต์กํ ๊ณ์ฐ๋ ์ํํ ์ ์์ด์! ์๋ฅผ ๋ค์ด, ํฉํ ๋ฆฌ์ผ ๊ฐ์ ์ํ ์ฐ์ฐ์ ์ปดํ์ผ ์๊ฐ์ ๊ณ์ฐํ ์ ์๋ต๋๋ค. ์ด๊ฑด ์ ๋ง ๋ง๋ฒ ๊ฐ์ ์ผ์ด์ฃ !
๐ญ ์ ์ ์ด์ค์ ์ ์ค์ ์์ฉ
์, ์ด์ ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ด ๋ง๋ฒ์ ์ค์ ๋ก ์ด๋ป๊ฒ ์ฌ์ฉํ ์ ์๋์ง ์ดํด๋ณผ๊น์? ์ฌ๋ฅ๋ท์์ ์๋ก์ด ๊ธฐ์ ์ ๋ฐฐ์ฐ๊ณ ๋ฐ๋ก ์ ์ฉํ๋ ๊ฒ์ฒ๋ผ, ์ฐ๋ฆฌ๋ ํ์ ํน์ฑ๊ณผ ์ ์ ์ด์ค์ ์ ์ค์ ์ฝ๋์ ์ ์ฉํด๋ด์!
๐ก๏ธ ์์ ํ ํจ์ ํ ํ๋ฆฟ ๋ง๋ค๊ธฐ
ํจ์ ํ ํ๋ฆฟ์ ์์ฑํ ๋, ํน์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ํ์ ๋ง ๋ฐ๊ณ ์ถ์ ๋๊ฐ ์์ฃ . ์ด๋ด ๋ ์ ์ ์ด์ค์ ์ด ํฐ ๋์์ด ๋ฉ๋๋ค.
template <typename T>
void safeDelete(T* ptr) {
static_assert(std::is_object<T>::value, "T must be an object type");
static_assert(!std::is_array<T>::value, "Array types are not allowed");
delete ptr;
}
// ์ฌ์ฉ ์
int* intPtr = new int(10);
safeDelete(intPtr); // OK
int arr[] = {1, 2, 3};
// safeDelete(arr); // ์ปดํ์ผ ์ค๋ฅ! ๋ฐฐ์ด์ ํ์ฉ๋์ง ์์ต๋๋ค.
์ด safeDelete
ํจ์๋ ๊ฐ์ฒด ํ์
์ ํฌ์ธํฐ๋ง ๋ฐ์๋ค์ด๊ณ , ๋ฐฐ์ด์ ๊ฑฐ๋ถํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด delete[]
๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๋ฐฐ์ด์ ์ค์๋ก delete
ํ๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ ๋ฌธ๊ฐ์ ์กฐ์ธ์ ๋ฐ์ ์ค์๋ฅผ ๋ฏธ๋ฆฌ ๋ฐฉ์งํ๋ ๊ฒ๊ณผ ๊ฐ์ฃ ! ๐ก๏ธ
๐๏ธโโ๏ธ ์ต์ ํ๋ ํจ์ ์ค๋ฒ๋ก๋ฉ
๋๋ก๋ ํ์ ์ ๋ฐ๋ผ ๋ค๋ฅธ ๊ตฌํ์ ์ ๊ณตํ๊ณ ์ถ์ ๋๊ฐ ์์ด์. ํ์ ํน์ฑ์ ์ด์ฉํ๋ฉด ์ด๋ฅผ ์ฐ์ํ๊ฒ ํด๊ฒฐํ ์ ์์ต๋๋ค.
// ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ
template <typename T>
typename std::enable_if<!std::is_integral<T>::value, void>::type
process(T value) {
std::cout << "์ผ๋ฐ ์ฒ๋ฆฌ: " << value << std::endl;
}
// ์ ์ ํ์
์ธ ๊ฒฝ์ฐ
template <typename T>
typename std::enable_if<std::is_integral<T>::value, void>::type
process(T value) {
std::cout << "์ ์ ์ฒ๋ฆฌ: " << value * 2 << std::endl;
}
// ์ฌ์ฉ ์
process(3.14); // ์ถ๋ ฅ: ์ผ๋ฐ ์ฒ๋ฆฌ: 3.14
process(42); // ์ถ๋ ฅ: ์ ์ ์ฒ๋ฆฌ: 84
์ด ์์ ์์๋ std::enable_if
๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ ํ์
๊ณผ ๊ทธ ์ธ์ ํ์
์ ๋ํด ๋ค๋ฅธ ๊ตฌํ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ ๋ง์น ์ฌ๋ฅ๋ท์์ ๊ฐ ๋ถ์ผ์ ์ ๋ฌธ๊ฐ๋ค์ด ์์ ์ ์ ๋ฌธ ์์ญ์ ๋ง๋ ์๋น์ค๋ฅผ ์ ๊ณตํ๋ ๊ฒ๊ณผ ๋น์ทํด์! ๐ฏ
โ ๏ธ ์ฃผ์: ํ ํ๋ฆฟ ๋ฉํํ๋ก๊ทธ๋๋ฐ์ ๊ฐ๋ ฅํ์ง๋ง, ๊ณผ๋ํ๊ฒ ์ฌ์ฉํ๋ฉด ์ฝ๋์ ๊ฐ๋ ์ฑ์ ํด์น ์ ์์ด์. ํญ์ ๊ท ํ์ ์ ์งํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค!
๐จ ํ์ ํน์ฑ์ ์์ ์ ํ์ฉ
์ง๊ธ๊น์ง ์ฐ๋ฆฌ๋ ํ์ ํน์ฑ๊ณผ ์ ์ ์ด์ค์ ์ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ๋ฒ์ ์ดํด๋ดค์ด์. ํ์ง๋ง ์ด ๋๊ตฌ๋ค์ ๋จ์ํ ํ์ ์ฒดํฌ๋ฅผ ๋์ด์ ์ ๋ง ์ฐฝ์์ ์ธ ๋ฐฉ์์ผ๋ก ํ์ฉ๋ ์ ์๋ต๋๋ค. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ๊ฐ์ง ์ฌ๋๋ค์ด ๋ชจ์ฌ ์๋ก์ด ์ํ์ ๋ง๋ค์ด๋ด๋ ๊ฒ์ฒ๋ผ ๋ง์ด์์! ๐ญ
๐งฉ ์ปดํ์ผ ์๊ฐ ํ์ ํผ์ฆ
ํ์ ํน์ฑ์ ์ด์ฉํ๋ฉด ์ปดํ์ผ ์๊ฐ์ ๋ณต์กํ ํ์ ํผ์ฆ์ ํ ์ ์์ด์. ์๋ฅผ ๋ค์ด, ์ฃผ์ด์ง ์กฐ๊ฑด์ ๋ฐ๋ผ ํ์ ์ ์ ํํ๋ ๋ฉํํจ์๋ฅผ ๋ง๋ค์ด๋ณผ๊น์?
template <typename T, typename U, typename V>
struct choose_type {
using type = typename std::conditional<
std::is_same<T, U>::value,
V,
typename std::conditional<
std::is_same<T, V>::value,
U,
T
>::type
>::type;
};
// ์ฌ์ฉ ์
using result1 = choose_type<int, int, float>::type; // float
using result2 = choose_type<int, float, int>::type; // float
using result3 = choose_type<int, float, double>::type; // int
์ด choose_type
๊ตฌ์กฐ์ฒด๋ ์ธ ๊ฐ์ง ํ์
์ ๋ฐ์์, ์ฒซ ๋ฒ์งธ ํ์
์ด ๋ ๋ฒ์งธ๋ ์ธ ๋ฒ์งธ ํ์
๊ณผ ๊ฐ์ผ๋ฉด ๋๋จธ์ง ํ๋๋ฅผ ์ ํํ๊ณ , ๋ชจ๋ ๋ค๋ฅด๋ฉด ์ฒซ ๋ฒ์งธ ํ์
์ ์ ํํฉ๋๋ค. ์ด๋ฐ ์์ ํ์
ํผ์ฆ์ ๋ณต์กํ ํ
ํ๋ฆฟ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค๊ณํ ๋ ๋งค์ฐ ์ ์ฉํ ์ ์์ด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ ์ ๋ฌธ๊ฐ์ ์ง์์ ์กฐํฉํด ์๋ก์ด ์๋ฃจ์
์ ๋ง๋ค์ด๋ด๋ ๊ฒ๊ณผ ๋น์ทํ์ฃ ! ๐ง ๐ก
๐ฎ ๋ฏธ๋๋ฅผ ์์ธกํ๋ ์ฝ๋
ํ์
ํน์ฑ์ ์ด์ฉํ๋ฉด ๋ฏธ๋์ C++ ํ์ค์์ ์ ๊ณตํ ๊ธฐ๋ฅ์ ๋ฏธ๋ฆฌ ๊ตฌํํด๋ณผ ์๋ ์์ด์. ์๋ฅผ ๋ค์ด, C++20์์ ๋์
๋ std::remove_cvref
๋ฅผ C++17์์ ๊ตฌํํด๋ณผ๊น์?
template <typename T>
struct remove_cvref {
using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
};
template <typename T>
using remove_cvref_t = typename remove_cvref<T>::type;
// ์ฌ์ฉ ์
static_assert(std::is_same<remove_cvref_t<const int&>, int>::value, "Should be int");
static_assert(std::is_same<remove_cvref_t<volatile int&&>, int>::value, "Should be int");
์ด๋ ๊ฒ ๊ตฌํํ remove_cvref
๋ ์ฐธ์กฐ์ const/volatile ํ์ ์๋ฅผ ๋ชจ๋ ์ ๊ฑฐํฉ๋๋ค. ์ด๋ฐ ์์ผ๋ก ๋ฏธ๋์ ๊ธฐ๋ฅ์ ๋ฏธ๋ฆฌ ๊ตฌํํด๋ณด๋ฉด, ์ฝ๋์ ํธํ์ฑ์ ๋์ด๊ณ ์๋ก์ด ํ์ค์ผ๋ก์ ์ ํ์ ์ฝ๊ฒ ๋ง๋ค ์ ์์ด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ฏธ๋์ ํธ๋ ๋๋ฅผ ์์ธกํ๊ณ ์ค๋นํ๋ ๊ฒ๊ณผ ๊ฐ์ฃ ! ๐ฎโจ
๐ก ๊ฟํ: ์๋ก์ด C++ ํ์ค์ด ๋์ฌ ๋๋ง๋ค ํ์ ํน์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ดํด๋ณด์ธ์. ์ข ์ข ๋งค์ฐ ์ ์ฉํ๊ณ ํฅ๋ฏธ๋ก์ด ์๋ก์ด ๋๊ตฌ๋ค์ด ์ถ๊ฐ๋ฉ๋๋ค!
๐๏ธ ์์ ํ ์ฝ๋ ์ํคํ ์ฒ ์ค๊ณํ๊ธฐ
ํ์ ํน์ฑ๊ณผ ์ ์ ์ด์ค์ ์ ํ์ฉํ๋ฉด ๋ ์์ ํ๊ณ ๊ฒฌ๊ณ ํ ์ฝ๋ ์ํคํ ์ฒ๋ฅผ ์ค๊ณํ ์ ์์ด์. ์ด๋ ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ ์ ๋ฌธ๊ฐ๋ค์ ์กฐ์ธ์ ์ข ํฉํด ์๋ฒฝํ ํ๋ก์ ํธ ๊ณํ์ ์ธ์ฐ๋ ๊ฒ๊ณผ ๊ฐ๋ต๋๋ค! ๐ทโโ๏ธ๐๏ธ
๐ ๏ธ ํ์ ์์ ํ ํฉํ ๋ฆฌ ํจํด
ํฉํ ๋ฆฌ ํจํด์ ๊ฐ์ฒด ์์ฑ์ ์บก์ํํ๋ ๋์์ธ ํจํด์ด์์. ํ์ ํน์ฑ์ ์ด์ฉํ๋ฉด ์ด ํจํด์ ๋์ฑ ์์ ํ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
class Animal { public: virtual ~Animal() = default; };
class Dog : public Animal {};
class Cat : public Animal {};
template <typename T>
class AnimalFactory {
static_assert(std::is_base_of<Animal, T>::value, "T must be derived from Animal");
public:
static std::unique_ptr<Animal> create() {
return std::make_unique<T>();
}
};
// ์ฌ์ฉ ์
auto dog = AnimalFactory<Dog>::create();
auto cat = AnimalFactory<Cat>::create();
// auto invalid = AnimalFactory<int>::create(); // ์ปดํ์ผ ์ค๋ฅ!
์ด ์์ ์์ AnimalFactory
๋ Animal
์ ํ์ ํด๋์ค๋ง ์์ฑํ ์ ์๋๋ก ์ ํ๋ฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์๋ชป๋ ํ์
์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ ๊ฒ์ ์ปดํ์ผ ์๊ฐ์ ๋ฐฉ์งํ ์ ์์ด์. ์ฌ๋ฅ๋ท์์ ๊ฐ ๋ถ์ผ์ ์ ๋ฌธ๊ฐ๋ง์ด ํด๋น ๋ถ์ผ์ ์๋น์ค๋ฅผ ์ ๊ณตํ ์ ์๋ ๊ฒ๊ณผ ๋น์ทํ์ฃ ! ๐พ
๐งฌ ํ์ ํน์ฑ์ ์ด์ฉํ ์ ์ฑ ๊ธฐ๋ฐ ์ค๊ณ
์ ์ฑ ๊ธฐ๋ฐ ์ค๊ณ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ธ๋ถ ๊ตฌํ์ ์ ์ฑ ํด๋์ค๋ก ๋ถ๋ฆฌํ๋ ๊ธฐ๋ฒ์ด์์. ํ์ ํน์ฑ์ ์ด์ฉํ๋ฉด ์ด๋ฅผ ๋์ฑ ์ ์ฐํ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
// ๋ก๊น
์ ์ฑ
struct ConsoleLogging {
static void log(const std::string& message) {
std::cout << "Console: " << message << std::endl;
}
};
struct FileLogging {
static void log(const std::string& message) {
// ํ์ผ์ ๋ก๊ทธ ์์ฑ (๊ฐ๋จํ ํํ)
std::cout << "File: " << message << std::endl;
}
};
// ๋ก๊ฑฐ ํด๋์ค
template <typename LogPolicy>
class Logger {
static_assert(std::is_class<LogPolicy>::value, "LogPolicy must be a class");
public:
static void log(const std::string& message) {
LogPolicy::log(message);
}
};
// ์ฌ์ฉ ์
Logger<ConsoleLogging>::log("Hello, Console!");
Logger<FileLogging>::log("Hello, File!");
์ด ์์ ์์๋ ๋ก๊น
๋ฐฉ์์ ์ ์ฑ
์ผ๋ก ๋ถ๋ฆฌํ๊ณ , Logger
ํด๋์ค๊ฐ ์ด ์ ์ฑ
์ ํ
ํ๋ฆฟ ์ธ์๋ก ๋ฐ์ ์ฌ์ฉํฉ๋๋ค. static_assert
๋ฅผ ํตํด LogPolicy
๊ฐ ํด๋์ค ํ์
์ธ์ง ํ์ธํ์ฌ ์์ ์ฑ์ ๋์์ด์. ์ด๋ ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ ๋ฌธ๊ฐ๋ค์ ์๋น์ค๋ฅผ ์กฐํฉํด ๋ง์ถคํ ์๋ฃจ์
์ ๋ง๋๋ ๊ฒ๊ณผ ๋น์ทํ๋ต๋๋ค! ๐งฉโจ
๐ ์ฌํ ํ: SFINAE(Substitution Failure Is Not An Error) ๊ธฐ๋ฒ๊ณผ ํ์ ํน์ฑ์ ๊ฒฐํฉํ๋ฉด ๋์ฑ ๊ฐ๋ ฅํ ํ ํ๋ฆฟ ๋ฉํํ๋ก๊ทธ๋๋ฐ์ด ๊ฐ๋ฅํด์. ์ด๋ฅผ ํตํด ์ปดํ์ผ ์๊ฐ์ ๋ณต์กํ ํ์ ์ ํ ๋ก์ง์ ๊ตฌํํ ์ ์๋ต๋๋ค!
๐ ๊ณ ๊ธ ๊ธฐ๋ฒ: ํ์ ํน์ฑ์ ์์
์, ์ด์ ์ฐ๋ฆฌ๋ ํ์ ํน์ฑ๊ณผ ์ ์ ์ด์ค์ ์ ๊ธฐ๋ณธ์ ๋ง์คํฐํ์ด์. ํ์ง๋ง ์ด ๋๊ตฌ๋ค์ ์ง์ ํ ํ์ ๋ ๊น์ ๊ณณ์ ์๋ต๋๋ค. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ด๋ณด์์์ ์ ๋ฌธ๊ฐ๋ก ์ฑ์ฅํ๋ ๊ณผ์ ์ฒ๋ผ, ์ฐ๋ฆฌ๋ ์ด์ ๋ ๊ณ ๊ธ ๊ธฐ๋ฒ์ผ๋ก ๋์๊ฐ๋ณผ๊น์? ๐โจ
๐งโโ๏ธ ํ์ ๋ฆฌ์คํธ์ ๋ฉํํจ์
ํ์ ๋ฆฌ์คํธ๋ ์ปดํ์ผ ์๊ฐ์ ํ์ ๋ค์ ์ํ์ค๋ฅผ ๋ค๋ฃจ๋ ๊ฐ๋ ฅํ ๋๊ตฌ์์. ์ด๋ฅผ ์ด์ฉํด ๋ณต์กํ ๋ฉํํจ์๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
// ํ์
๋ฆฌ์คํธ
template <typename... Ts>
struct TypeList {};
// ํ์
๋ฆฌ์คํธ์ ๊ธธ์ด๋ฅผ ๊ตฌํ๋ ๋ฉํํจ์
template <typename List>
struct Length;
template <typename... Ts>
struct Length<TypeList<Ts...>> : std::integral_constant<std::size_t, sizeof...(Ts)> {};
// n๋ฒ์งธ ํ์
์ ์ป๋ ๋ฉํํจ์
template <std::size_t N, typename List>
struct NthType;
template <std::size_t N, typename T, typename... Ts>
struct NthType<N, TypeList<T, Ts...>> : NthType<N-1, TypeList<Ts...>> {};
template <typename T, typename... Ts>
struct NthType<0, TypeList<T, Ts...>> {
using type = T;
};
// ์ฌ์ฉ ์
using MyList = TypeList<int, float, double, char>;
static_assert(Length<MyList>::value == 4, "Length should be 4");
static_assert(std::is_same<NthType<2, MyList>::type, double>::value, "3rd type should be double");
์ด ์์ ์์๋ ํ์ ๋ฆฌ์คํธ๋ฅผ ์ ์ํ๊ณ , ๊ทธ ๊ธธ์ด๋ฅผ ๊ตฌํ๊ฑฐ๋ ํน์ ์์น์ ํ์ ์ ์ป๋ ๋ฉํํจ์๋ฅผ ๊ตฌํํ์ด์. ์ด๋ฐ ๊ธฐ๋ฒ์ ๋ณต์กํ ํ ํ๋ฆฟ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค๊ณํ ๋ ๋งค์ฐ ์ ์ฉํฉ๋๋ค. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ ์ ๋ฌธ๊ฐ์ ๊ธฐ์ ์ ์กฐํฉํด ์๋ก์ด ์๋น์ค๋ฅผ ๋ง๋ค์ด๋ด๋ ๊ฒ๊ณผ ๊ฐ์ฃ ! ๐งโโ๏ธ๐ฎ
๐๏ธ CRTP์ ํ์ ํน์ฑ์ ๊ฒฐํฉ
CRTP(Curiously Recurring Template Pattern)๋ ์ ์ ๋คํ์ฑ์ ๊ตฌํํ๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฒ์ด์์. ์ด๋ฅผ ํ์ ํน์ฑ๊ณผ ๊ฒฐํฉํ๋ฉด ๋์ฑ ์ ์ฐํ๊ณ ์์ ํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
template <typename Derived>
class Base {
public:
void interface() {
static_assert(std::is_base_of<Base<Derived>, Derived>::value,
"Derived must inherit from Base");
static_cast<Derived*>(this)->implementation();
}
protected:
~Base() = default;
};
class Derived : public Base<Derived> {
public:
void implementation() {
std::cout << "Derived implementation" << std::endl;
}
};
// ์ฌ์ฉ ์
Derived d;
d.interface(); // ์ถ๋ ฅ: Derived implementation
์ด ์์ ์์ Base
ํด๋์ค๋ CRTP๋ฅผ ์ฌ์ฉํ์ฌ Derived
ํด๋์ค์ implementation( )
๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค. static_assert
๋ฅผ ์ฌ์ฉํ์ฌ Derived
๊ฐ ์ค์ ๋ก Base
๋ฅผ ์์๋ฐ์๋์ง ํ์ธํ์ฌ ์์ ์ฑ์ ๋์์ด์. ์ด๋ ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ฉํ ์ ๋ฉํฐ ๊ด๊ณ๋ฅผ ์ค์ ํ ๋, ์ ์ ํ ์๊ฒฉ์ ๊ฐ์ถ ์ฌ๋๋ค๋ง ์ฐ๊ฒฐ๋๋๋ก ํ๋ ๊ฒ๊ณผ ๋น์ทํ๋ต๋๋ค! ๐ฅ๐
๐ก ํ๋ก ํ: CRTP๋ ๊ฐ์ ํจ์๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ ๋คํ์ฑ์ ๊ตฌํํ ์ ์์ด, ์ฑ๋ฅ ๋ฉด์์ ์ด์ ์ด ์์ด์. ํ์ง๋ง ์ฌ์ฉ์ ์ฃผ์๊ฐ ํ์ํ๋ฉฐ, ์ฝ๋์ ๋ณต์ก์ฑ์ ์ฆ๊ฐ์ํฌ ์ ์์ต๋๋ค.
๐ญ ์ค์ ์์ฉ: ํ์ ํน์ฑ์ ๋ง๋ฒ ์์ ํ๊ธฐ
์, ์ด์ ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ด ๋ชจ๋ ๊ฒ์ ์ข ํฉํด์ ์ค์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด๋ณผ๊น์? ์ด๋ ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ๋ถ์ด ๋ฐฐ์ด ๊ธฐ์ ์ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ๋ ๊ฒ๊ณผ ๊ฐ์์! ๐จโจ
๐งช ์์ ํ ๋ค์ฐจ์ ๋ฐฐ์ด ๋ํผ
๋ค์ฐจ์ ๋ฐฐ์ด์ ์์ ํ๊ฒ ๋ค๋ฃฐ ์ ์๋ ๋ํผ ํด๋์ค๋ฅผ ๋ง๋ค์ด๋ด ์๋ค. ์ด ํด๋์ค๋ ์ปดํ์ผ ์๊ฐ์ ์ฐจ์ ์๋ฅผ ํ์ธํ๊ณ , ์๋ชป๋ ์ ๊ทผ์ ๋ฐฉ์งํ ๊ฑฐ์์.
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ