#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;
}