"(c++20) Conditional Explicit Constructor"
1. explicit // c++11
struct NoExplicit
{
NoExplicit() = default;
NoExplicit(int n)
{
cout << n << endl;
}
};
void TestNoExplicit(NoExplicit a)
{
}
int main(void)
{
NoExplicit a;
TestNoExplicit(a);
TestNoExplicit(10); // - ???? error X
}
TestNoExplicit(10); // - ???? error X
TestNoExplicit() NoExplicit struct ์๋ฃํ์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๊ณ ์๋ค. ๊ทธ๋ผ ๋งค๊ฐ๋ณ์์ NoExplicit struct ์ด ์ธ์ ๋ค๋ฅธ ์๋ฃํ์ด ๋ค์ด๊ฐ๋ค๋ฉด ์๋ฌ๋ฅผ ๋ฑ์ด๋ด๋๊ฒ ์ ์์ด๋ค. ํ์ง๋ง ์ ์ฝ๋์์ TestNoExplicit(10) ์๋ฌ๋ฅผ ๋ฑ์ด ๋ผ๊ฑฐ ๊ฐ์ง๋ง ์ ์ ์๋ํ๋ค.
์ด๋ ์ปดํ์ผ๋ฌ์์ "10"์ NoExplicit(int n)" ์์ฑ์๋ฅผ ์ด์ฉํ์ฌ ์์์ ํ๋ณํ์ ํ์ฉํ๊ธฐ ๋๋ฌธ์ ์ด๋ค.
์ด๋ฌํ ์์์ ํ๋ณํ์ ์ ํ ํ๋ ํค์๋๊ฐ ๋ฐ๋ก c++11์ ์ถ๊ฐ ๋ [explicit: ๋ช ํํ๋ค. ๋ช ์์ ์ด๋ค.] ์ด๋ค. ์ฆ, ๋ด๊ฐ ์ง์ ํ ์์ฑ์ ์๋ฃํ(ํด๋์ค, ๊ตฌ์กฐ์ฒด) ์ธ์๋ ๋ช ์์ ์ธ ํ๋ณํ์ ํ์ฉํ์ง ์๊ฒ ๋ค๋ ๋ป์ด๋ค.
์ด ํค์๋๋ฅผ NoExplicit ํจ์์ ๋ถ์ฌ์ฃผ๊ฒ ๋๋ฉด,
explicit NoExplicit(int n)
{
cout << n << endl;
}
TestNoExplicit(10); ์ด ๋ถ๋ถ์ด ์์์ ํ๋ณํ์ผ๋ก error๋ฅผ ๋ฑ์ง ์์๋๋ฐ NoExplicit ์์ฑ์์ explicit๋ฅผ ๋ถ์ฌ์ค์ผ๋ก์ TestNoExplicit(10);๋ error ๋ฑ๋๋ค.
2. conditional explicit // c++20
c++20๋ถํฐ๋ explicit(bool)์ด ์ถ๊ฐ๋์ด ํน์ ์กฐ๊ฑด์ผ ๋๋ง explicit๋ก ๋์ํ๊ฒ ํ ์ ์๋ค.
condition explicit : ์กฐ๊ฑด ๋ถ๋ก ์ํ์ง ์์ ํ๋ณํ์ด ์ผ์ด๋์ง ์๋๋ก ์ ํํ๋ค.
struct ConditionExplicit
{
ConditionExplicit() = default;
template<typename T>
explicit (!std::is_same < T, bool>::value) ConditionExplicit( T n)
{
cout << n << endl;
}
};
[1๋ฒ]
void f(std::string);
f("hello"); //๋ฌธ์ ๋ฆฌํฐ๋ด ๋ช
์์ ํ๋ณํ
f("hello"sv); // std::string_view ๋ช
์์ ํ๋ณํ ํ์ฉx
[2๋ฒ]
template<class T>
struct wrapper {
template <class U>
wrapper(U const& u) : t_(u) {}
T t_;
};
void g(wrapper<std::string>);
g("hello"); //this should compile
g("hello"sv); //this should not
[1๋ฒ]์ f("hello"sv) ๋ ์ปดํ์ผ error๋ฅผ ๋ฐ์์ํค๊ณ , [2๋ฒ]์ g("hello"sv)๋ ์ปดํ์ผ error๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ์ํด ํน์ ์ปดํ์ผ ์กฐ๊ฑด์์ ํจ์ ํ ํ๋ฆฟ์ ๋ฌด์ํ ์ ์๋๋ก ํด์ฃผ๋ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํฌํผ ํ ํ๋ฆฟ std::enable_if<>๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑํ๋ฉด ํด๊ฒฐ ํ ์ ์๋ค.
template<class T>
struct wrapper {
template<class U, std::enable_if_t<std::is_convertible_v<U, T>>* = nullptr>
wrapper(U const& u) : t_(u) {}
template<class U, std::enable_if_t<!std::is_convertible_v<U, T>>* = nullptr>
explicit wrapper(U const& u) : t_(u) {}
T t_;
};
์ ์ฝ๋๋ ์ค์ ๋ก ํ๋์ด์ฌ์ผ ํ๋ ์ฝ๋๊ฐ ๋๊ฐ ์กด์ฌํ๊ณ SFINAE(substiution failure is not an error/์นํ ์คํจ๋ ์๋ฌ๊ฐ ์๋๋ค)๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์ค ํ๋๋ฅผ ์ ํํ๋ค. ์ด๋ฒ c++20์ ์ถ๊ฐ๋ conditional explicit๋ ์ด๋ฅผ ํ ๋ฒ์ ํด๊ฒฐํ๋ค.
template<class T>
struct wrapper {
template<class U>
explicit(!std::is_convertible_v<U, T>)
wrapper(U const& u) : t_(u) {}
T t_;
};
void g(wrapper<std::string>);
g("hello");
g("hello"sv);
โป is_convertible_v ํ ํ๋ฆฟ์ ๋ณํํ ์๋ณธ ํ์ U, ๋ณํํ ๋์ ํ์T (U=T)์ด ์ฌ๋ฐ๋ฅธ ํ์์ธ ๊ฒฝ์ฐ true๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ false๋ฅผ return ํ๋ค.
์ ์ฝ๋๋ฅผ ์ค๋ช ํ๋ฉด ์๋์ ๊ฐ๋ค.
์กฐ๊ฑด๋ถ๋ก ์ํ์ง ์๋ ํ๋ณํ์ ์ผ์ด๋์ง ์๋๋ก ๋ง์ ์ ์๋๋ก explicit(bool) bool ๋ถ๋ถ์ ์กฐ๊ฑด์ ๋ฃ์ด์ค๊ฒ์ด๋ค.
explicit(!std::is_convertible_v<U, T>):
!(T๊ฐ U๋ก ๋ณํ๊ฐ๋ฅํ ๋ == std::is_convertible_v<U,T> == true) = T๊ฐ U๋ก ๋ณํ๊ฐ๋ฅํ์ง ์์ ๋๋ง explicit ์ด๋ค.
g("hello"sv)
U: std::string
T: std::string_view
T( std::string_view )๊ฐ U( std::string )๋ก ๋ณํ์ด ๊ฐ๋ฅํ์ง ์์์ ์์์ ํ๋ณํ์ ํ์ฉํ์ง ์๋๋ค. explicit๋ก ์ฐจ๋จํจ.
void g(wrapper<std::string_view>);
gํจ์ ํ ํ๋ฆฟ ๋งค๊ฐ๋ณ์๊ฐ string_view๋ก ์ง์ ํ๋ค๋ฉด
g("hello"sv)
U: std::string_view
T: std::string
T( std::string )๊ฐ U( std::string_view )๋ก ๋ณํ์ด ๊ฐ๋ฅํ์ฌ ์์์ ํ๋ณํ์ ํ์ฉํ๋ค.
โป enable_if
enable_if๋ c++์ ๋ํดํ ํน์ฑ ์ค ํ๋์ธ SFINAE(substiution failure is not an error/์นํ ์คํจ๋ ์๋ฌ๊ฐ ์๋๋ค)์ ๊ธฐ๋ฐ์ ๋๊ณ ์๋ค. SFINAE(substiution failure is not an error/์นํ ์คํจ๋ ์๋ฌ๊ฐ ์๋๋ค) : ์ค๋ฒ๋ก๋ฉ๋ ํจ์๊ฐ ์ฌ๋ฌ ๊ฐ ์์ ๋ enable_if๋ฅผ ์ด์ฉํ์ฌ ํน์ ํ ํ์ ํธ๋ ์ดํธ์ ๋ฐ๋ผ ์ค๋ฒ๋ก๋ฉ๋ ํจ์ ์ค ์ผ๋ถ๋ฅผ ๋ ์ ์๋ค. enable_ifํธ๋ ์ดํธ๋ ์ค๋ฒ๋ก๋ฉ ํจ์๋ค์ ๋ํ ๋ฆฌํด ํ์ ์ ๊ธฐ์ค์ผ๋ก ๋ถ๊ธฐํ ๋ ์ฃผ๋ก ์ฌ์ฉ๋๋ค. enable_if๋ ํ ํ๋ฆฟ ํ์ ๋งค๊ฐ๋ณ์๋ฅผ ๋ ๊ฐ ๋ฐ๋๋ค. ํ๋๋ bool. ๋ค๋ฅธ ํ๋๋ ํ์ ์ธ๋ฐ ๋ํดํธ๊ฐ์ void๋ค. C++ ํ์ค์ enalbe_if์ฒ๋ผ type๋ฉค๋ฒ๋ฅผ ๊ฐ์ง ํธ๋ ์ดํธ์ ๋ํ ์จ๋ฆฌ์ด์คํ ํ๋ฆฟ์ ๋ช๊ฐ์ง ์ ์ํ๊ณ ์๊ณ , ๊ฐ๊ฐ์ ์ด๋ฆ์ ํธ๋ ์ดํธ ์ด๋ฆ ๋ค์ _t๊ฐ ๋ถ์ด ์๋ค. typename enable_if<...., bool>::type enable_if_t<...., bool> enable_if_t์ ์ฒซ๋ฒ ์งธ ์ธ์๊ฐ true๋ฉด enable_if_t๋ bool ํ์ ์ ๊ฐ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ํ์ ์ด ์๋ค. ๋ฐ๋ก ์ฌ๊ธฐ์ SFINAE๊ฐ ์ ์ฉ๋๋ค. ์ธ์คํด์คํ ํ๋ ๊ณผ์ ์์ ์๋ฌด๋ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์ผ๋ฉด ์ปดํ์ผ๋ฌ๋ ์ด ๋ฒ์ ์ check_type()์ ์ ์ฉํ๋ค.
1. ๋ด์ฉ ์ถ์ : ์ธํ๋ฐ Inflearn - Rookiss ์ค ๊ฐ์์ธ C++20 ํ์ด๋ณด๊ธฐ ์ค.
2. https://devblogs.microsoft.com/
'๐จ๐ปโ๐ป programming > โฝ c, c++' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
(c++20) STL::Container #2 - contains, starts_with, ends_with (2) | 2024.06.17 |
---|---|
(c++20) STL::Container #1 - std::to_array, erase, erase_if (0) | 2024.06.17 |
(c++20) [Three-way Comparsion(3๋ฐฉํฅ ๋น๊ต ์ฐ์ฐ์)/์ฐ์ฃผ์ ] ์ฐ์ฐ์ (0) | 2024.06.14 |
(c++20) consteval, constinit (0) | 2024.06.14 |
[c++17] ์ ๋ฌธ์๋ฅผ ์ํ c++17 ์๋ก์ด ๋ด์ฉ ๋ถ๋งํฌ (0) | 2024.03.11 |
์ ํ๋ ๊ฒ ๋ณด๋ค ๋ซ๊ฒ ์ง
ํฌ์คํ ์ด ์ข์๋ค๋ฉด "์ข์์โค๏ธ" ๋๋ "๊ตฌ๋ ๐๐ป" ํด์ฃผ์ธ์!