- #include <iostream> 
- using namespace std; 
-   
-   
- template <typename T> 
- struct St1 
- { 
-     St1 () = default; 
-   
-     St1 (const St1& other) : hasValue (other.hasValue) { if (hasValue) value = other.value; } 
-   
-     St1 (St1&& other) : hasValue (other.hasValue) { if (hasValue) value = std::move(other.value); } 
-   
- 	template <typename Arg0, typename... Args > 
-     explicit St1 (Arg0 arg0, Args&&... args) : hasValue (true) { value = T(std::forward<Arg0>(arg0), std::forward<Args>(args)...); } 
-   
- 	T value; 
- 	bool hasValue { false }; 
- }; 
-   
- template <typename T> 
- struct St2 
- { 
-     St2 () = default; 
-   
-     St2 (const St2& other) : hasValue (other.hasValue) { if (hasValue) value = other.value; } 
-   
-     St2 (St2&& other) : hasValue (other.hasValue) { if (hasValue) value = std::move(other.value); } 
-   
-     explicit St2 (const T &value) : hasValue (true) { this->hasValue = value; } 
-   
-     explicit St2 (T &&value) : hasValue (true) { this->value = std::move(value); } 
-   
- 	T value; 
- 	bool hasValue { false }; 
- }; 
-   
- template <typename T> 
- struct St3 
- { 
-     St3 () = default; 
-   
-     St3 (const St3& other) : hasValue (other.hasValue) { if (hasValue) value = other.value; } 
-   
-     St3 (St3&& other) : hasValue (other.hasValue) { if (hasValue) value = std::move(other.value); } 
-   
- 	template <typename... Args > 
-     explicit St3 (Args&&... args) : hasValue (true) { value = T(std::forward<Args>(args)...); } 
-   
- 	T value; 
- 	bool hasValue { false }; 
- }; 
-   
- template <typename T> 
- struct St4 
- { 
-     St4 () = default; 
-   
-     St4 (const St4& other) : hasValue (other.hasValue) { if (hasValue) value = other.value; } 
-   
-     St4 (St4&& other) : hasValue (other.hasValue) { if (hasValue) value = std::move(other.value); } 
-   
- 	explicit St4 (T value) : hasValue (true) { this->value = value; } 
-   
- 	template <typename... Args > 
-     explicit St4 (Args&&... args) : hasValue (true) { value = T(std::forward<Args>(args)...); } 
-   
- 	T value; 
- 	bool hasValue { false }; 
- }; 
-   
- template <typename T> 
- struct St5 
- { 
- 	St5 () {}; 
-   
-     St5 (const St5& other) : hasValue (other.hasValue) { if (hasValue) value = other.value; } 
-   
-     St5 (St5&& other) : hasValue (other.hasValue) { if (hasValue) value = std::move(other.value); } 
-   
- 	explicit St5 (T value) : hasValue (true) { this->value = value; } 
-   
- 	template <typename... Args > 
-     explicit St5 (Args&&... args) : hasValue (true) { value = T(std::forward<Args>(args)...); } 
-   
- 	T value; 
- 	bool hasValue { false }; 
- }; 
-   
-   
- int main() { 
-   
- 	St1<int> a1; 
- 	St1<int> a2 {2}; 
- 	St1<int> a3 {}; 
-   
- 	St2<int> b1; 
- 	St2<int> b2 {2}; 
- 	St2<int> b3 {}; 
-   
- 	St3<int> c1; 
- 	St3<int> c2 {2}; 
- 	St3<int> c3 {}; 
-   
- 	St4<int> d1; 
- 	St4<int> d2 {2}; 
- 	St4<int> d3 {}; 
-   
- 	St5<int> e1; 
- 	St5<int> e2 {2}; 
- 	St5<int> e3 {}; 
-   
- 	cout << "St1:\n"; 
- 	cout << (a1.hasValue == 0) << '\n'; 
- 	cout << (a2.hasValue == 1) << '\n'; 
- 	cout << (a2.value == 2) << '\n'; 
- 	cout << (a3.hasValue == 0) << '\n'; 
-   
- 	cout << "St2:\n"; 
- 	cout << (b1.hasValue == 0) << '\n'; 
- 	cout << (b2.hasValue == 1) << '\n'; 
- 	cout << (b2.value == 2) << '\n'; 
- 	cout << (b3.hasValue == 0) << '\n'; 
-   
- 	cout << "St3:\n"; 
- 	cout << (c1.hasValue == 0) << '\n';	// failed in VS 
- 	cout << (c2.hasValue == 1) << '\n';	// failed in VS 
- 	cout << (c2.value == 2) << '\n';	// failed in VS 
- 	cout << (c3.hasValue == 0) << '\n'; 
-   
- 	cout << "St4:\n"; 
- 	cout << (d1.hasValue == 0) << '\n';	// failed in VS 
- 	cout << (d2.hasValue == 1) << '\n'; 
- 	cout << (d2.value == 2) << '\n'; 
- 	cout << (d3.hasValue == 0) << '\n'; 
-   
- 	cout << "St5:\n"; 
- 	cout << (e1.hasValue == 0) << '\n'; 
- 	cout << (e2.hasValue == 1) << '\n'; 
- 	cout << (e2.value == 2) << '\n'; 
- 	cout << (e3.hasValue == 0) << '\n'; 
-   
- 	return 0; 
- }