t1.hpp ```c++ #include <string> #include <set> #include <vector> // #include <map> #include <unordered_map> #include <queue> #include<stdexcept> #include <algorithm> #ifndef Q1_HPP #define Q1_HPP namespace q1 { class neighbour { public: explicit neighbour(std::size_t rung_distance = 1); neighbour(const neighbour &other) = default; neighbour(neighbour &&other) noexcept = default; virtual ~neighbour() noexcept = default; // auto operator=(const neighbour &other) = default; // 1 // auto operator=(neighbour &&other) noexcept = default; // 2 auto get_rung() const noexcept -> std::size_t; virtual auto get_neighbours(const std::string &curr, const std::set<std::string> &lexicon) const -> std::set<std::string>; private: auto check(std::string a,std::string b) const -> bool; std::size_t rung_distance_; }; auto generate( const std::string &start, const std::string &end, const std::set<std::string> &lexicon, const neighbour &strategy ) -> std::vector<std::string>; } // namespace q1 #endif // Q1_HPP ``` t1.cpp ```c++ #include <q1/q1.hpp> namespace q1 { auto generate( const std::string &start, const std::string &end, const std::set<std::string> &lexicon, const neighbour &strategy ) -> std::vector<std::string> { if (start.size() != end.size()) { return {}; } std::unordered_map<std::string, std::set<std::string>> vis; std::queue<std::string> q; std::unordered_map<std::string, std::string> pa; while (!q.empty()) { int size = q.size(); while (size--) { auto f = q.front(); q.pop(); if (!vis.count(f)) { vis[f] = strategy.get_neighbours(f, lexicon); } auto& neibor = vis[f]; for (auto& p : neibor) { if (!pa.count(p)) pa[p] = f; if (!vis.count(p)) { q.push(p); } } } } bool ok = 1; std::string cur = end; std::vector<std::string> ans; ans.push_back(end); while (cur != start) { if (!pa.count(cur)) { ok = 0; break; } cur = pa[cur]; ans.push_back(cur); } std::reverse(ans.begin(), ans.end()); if (!ok) return {}; else return ans; } neighbour::neighbour(std::size_t rung_distance){ if (rung_distance == 0){ throw std::domain_error("rung_distance is zero"); } rung_distance_ = rung_distance; } auto neighbour::get_rung() const noexcept -> std::size_t{ return rung_distance_; } auto neighbour::check(std::string a,std::string b) const -> bool{ if( a.size() != b.size() ) return false; int count = 0; for(int i = 0 ; i< a.size();i++){ if(a[i]!=b[i]) count++; } return count==rung_distance_; } auto neighbour::get_neighbours(const std::string &curr, const std::set<std::string> &lexicon) const -> std::set<std::string>{ std::set<std::string> res{}; for( auto const& word:lexicon){ if ( check(curr,word) ) { res.insert(word); } } return res; } } // namespace q1 ``` ## T2 t2.hpp ```c++ #include <type_traits> #include <stdexcept> #ifndef Q2_HPP #define Q2_HPP namespace q2 { template <typename T> struct remove_array_ref { using type = typename std::remove_all_extents<typename std::remove_reference<T>::type>::type ; }; template <typename T> using remove_array_ref_t = typename remove_array_ref<T>::type; template <typename T, auto N> class sso_optional { public: using value_type = remove_array_ref_t<T>; using reference = value_type&; using pointer = std::conditional<std::is_class<value_type>::value, value_type*, void>; // std::enable_if<std::is_class<value_type>::value> // using pointer = value_type*; // std::enable_if<!std::is_class<value_type>::value> // using pointer = typename nullptr; T value; sso_optional() noexcept { // static_cast<reference>(*this) = N; value = N; } explicit sso_optional(const value_type &arg) noexcept { value = value_type(arg); } template<typename ...Args> explicit sso_optional(Args&& ...args) noexcept { value = value_type(std::forward<Args>(args)...); } sso_optional(const sso_optional &other) = delete; // 4 sso_optional(sso_optional &&other) noexcept { value = move(other); other = N; } ~sso_optional() noexcept { if (bool(value)) { if (!std::is_same<pointer, void>::value) { // delete static_cast<pointer>(value); } } } auto operator=(const sso_optional &other) -> sso_optional& = delete; // 1 auto operator=(sso_optional &&other) noexcept -> sso_optional& { if (this == &other) return static_cast<reference>(*this); // self if (bool(value) && !std::is_same<pointer, void>::value) { delete static_cast<pointer>(value); } value = move(other); other = N; } operator bool() const noexcept { return static_cast<value_type>(value) != N; } auto operator*() -> reference { if (value != N) { return static_cast<reference>(value); } else { throw std::runtime_error(); } } auto operator->() -> pointer { if (value != N) { return static_cast<pointer>(value); } else { throw std::runtime_error(); } } auto operator==(const sso_optional &other) const noexcept -> bool { if (value == N && other == N || (value != N && other != N && value == other)) { return true; } else { return false; } } }; } #endif // Q2_HPP ``` t2.cpp ```c++ ``` q2.hpp__ ```c++ #ifndef Q2_HPP #define Q2_HPP #include <type_traits> namespace q2 { #define SSO_MOV(x) static_cast<std::remove_reference_t<decltype(x)>&&>(x) #define SSO_FWD(x) static_cast<decltype(x)&&>(x) template <typename T> struct remove_array_ref { using type = typename std::remove_all_extents<typename std::remove_reference<T>::type>::type ; }; template <typename T> using remove_array_ref_t = typename remove_array_ref<T>::type; template <typename T, auto N> class sso_optional { constexpr void maybe_init_union(){ if (std::is_constant_evaluated()) dummy = N; } public: using value_type = remove_array_ref_t<T>; using reference = value_type &; using pointer = std::conditional<std::is_class<value_type>::value, value_type*, void>; sso_optional() noexcept; explicit sso_optional(const value_type &arg) noexcept; template<typename ...Args> explicit sso_optional(Args&& ...args) noexcept; sso_optional(const sso_optional &other) = delete; sso_optional(sso_optional &&other) noexcept; ~sso_optional() { if (!_state) return; value_.~T(); } constexpr void reset_no_check(){ if constexpr (not std::is_trivially_destructible_v<T>){ value_.~T(); } _state = false; } constexpr bool has_value() const noexcept { return this->_state; } union { char dummy; T value_; }; bool _state; // assign auto operator=(const sso_optional &other) -> sso_optional& = delete; auto operator=(sso_optional &&other) noexcept -> sso_optional&; // bool operator bool() const noexcept; auto operator*() -> reference; // 1 auto operator->() -> pointer; // 2 auto operator==(const sso_optional &other) const noexcept -> bool; private: template <class sso_optional> constexpr auto& assign_from_optional(sso_optional&& o){ switch( char(_state) + char(o.has_value()) * 2 ){ case 0 : break; case 1 : this->reset_no_check(); break; case 2 : this->construct_from(*SSO_FWD(o)); break; case 3 : **this = *SSO_FWD(o); break; } return *this; } template <class... Args> constexpr void construct_from(Args&&... args){ std::construct_at(std::addressof(value_), static_cast<Args&&>(args)...); _state = true; } template <class sso_optional> constexpr void construct_from_optional(sso_optional&& opt){ if (_state) this->construct_from(*SWL_FWD(opt)); else this->maybe_init_union(); } T* ptr(){ return std::addressof(value_); } const T* ptr() const { return std::addressof(value_); } }; template<typename T, auto N> sso_optional<T, N>::sso_optional() noexcept { _state = false; dummy = N; } template<typename T, auto N> sso_optional<T, N>::sso_optional(const value_type &arg) noexcept { construct_from_optional(arg); _state = arg._state; } template<typename T, auto N> template<typename... Args> sso_optional<T, N>::sso_optional(Args &&... args) noexcept { this->construct_from(SSO_FWD(args)...); _state = true; } template<typename T, auto N> sso_optional<T, N>::sso_optional(sso_optional &&other) noexcept { this->construct_from_optional(SSO_FWD(other)); _state = other.has_value(); } template<typename T, auto N> auto sso_optional<T, N>::operator=(sso_optional &&other) noexcept -> sso_optional & { return this->assign_from_optional(SSO_FWD(other)); } template<typename T, auto N> sso_optional<T, N>::operator bool() const noexcept { return has_value(); } template<typename T, auto N> auto sso_optional<T, N>::operator*() -> reference { if(_state) { return value_; } else { throw std::runtime_error("1"); } } template<typename T, auto N> auto sso_optional<T, N>::operator->() -> std::conditional<std::is_class<value_type>::value, value_type*, void> { if(!_state || typeid(pointer) == typeid(void)) { throw std::runtime_error("2"); } return this->ptr(); } template<typename T, auto N> auto sso_optional<T, N>::operator==(const sso_optional &other) const noexcept -> bool { if (this->has_value() != other.has_value()) return false; if (not this->has_value()) return true; return *this == *other; } } #endif // Q2_HPP ``` ```debug= q2.hpp:12:37: error: expected nested-name-specifier before ‘remove_array_ref_t’ 12 | using value_type = typename remove_array_ref_t<T>; | ^~~~~~~~~~~~~~~~~~ q2.hpp:13:36: error: expected nested-name-specifier before ‘value_type’ 13 | using reference = typename value_type&; | ^~~~~~~~~~ q2.hpp:16:34: error: expected nested-name-specifier before ‘value_type’ 16 | using pointer = typename value_type*; | ^~~~~~~~~~ q2.hpp:25:37: error: ‘value_type’ does not name a type 25 | explicit sso_optional(const value_type &arg) noexcept { | ^~~~~~~~~~ q2.hpp:65:29: error: ‘reference’ does not name a type 65 | auto operator*() -> reference { | ^~~~~~~~~ q2.hpp:72:30: error: ‘pointer’ does not name a type 72 | auto operator->() -> pointer { | ^~~~~~~ q2.hpp: In constructor ‘q2::sso_optional<T, N>::sso_optional()’: q2.hpp:22:25: error: ‘value_type’ does not name a type 22 | static_cast<value_type>(*this) = N; | ^~~~~~~~~~ q2.hpp: In constructor ‘q2::sso_optional<T, N>::sso_optional(const int&)’: q2.hpp:26:25: error: ‘value_type’ does not name a type 26 | static_cast<value_type>(*this) = value_type(arg); | ^~~~~~~~~~ q2.hpp:26:46: error: there are no arguments to ‘value_type’ that depend on a template parameter, so a declaration of ‘value_type’ must be available [-fpermissive] 26 | static_cast<value_type>(*this) = value_type(arg); | ^~~~~~~~~~ q2.hpp:26:46: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated) q2.hpp: In constructor ‘q2::sso_optional<T, N>::sso_optional(q2::sso_optional<T, N>&&)’: q2.hpp:37:25: error: ‘value_type’ does not name a type 37 | static_cast<value_type>(*this) = move(other); | ^~~~~~~~~~ q2.hpp: In destructor ‘q2::sso_optional<T, N>::~sso_optional()’: q2.hpp:42:34: error: ‘value_type’ was not declared in this scope 42 | if (bool(static_cast<value_type>(*this))) { | ^~~~~~~~~~ q2.hpp:42:17: error: expected primary-expression before ‘bool’ 42 | if (bool(static_cast<value_type>(*this))) { | ^~~~ q2.hpp:42:17: error: expected ‘)’ before ‘bool’ q2.hpp:42:16: note: to match this ‘(’ 42 | if (bool(static_cast<value_type>(*this))) { | ^ q2.hpp:43:35: error: ‘pointer’ was not declared in this scope 43 | if (!std::is_same<pointer, nullptr>::value) { | ^~~~~~~ q2.hpp:43:51: error: template argument 1 is invalid 43 | if (!std::is_same<pointer, nullptr>::value) { | ^ q2.hpp:43:51: error: type/value mismatch at argument 2 in template parameter list for ‘template<class, class> struct std::is_same’ q2.hpp:43:51: note: expected a type, got ‘nullptr’ q2.hpp:44:40: error: ‘value_type’ does not name a type 44 | delete static_cast<value_type>(*this); | ^~~~~~~~~~ q2.hpp: In member function ‘q2::sso_optional<T, N>& q2::sso_optional<T, N>::operator=(q2::sso_optional<T, N>&&)’: q2.hpp:52:52: error: ‘reference’ does not name a type 52 | if (this == &other) return static_cast<reference>(*this); // self | ^~~~~~~~~ q2.hpp:53:34: error: ‘value_type’ was not declared in this scope 53 | if (bool(static_cast<value_type>(*this)) && !std::is_same<pointer, nullptr>::value) { | ^~~~~~~~~~ q2.hpp:53:17: error: expected primary-expression before ‘bool’ 53 | if (bool(static_cast<value_type>(*this)) && !std::is_same<pointer, nullptr>::value) { | ^~~~ q2.hpp:53:17: error: expected ‘)’ before ‘bool’ q2.hpp:53:16: note: to match this ‘(’ 53 | if (bool(static_cast<value_type>(*this)) && !std::is_same<pointer, nullptr>::value) { | ^ q2.hpp:54:36: error: ‘value_type’ does not name a type 54 | delete static_cast<value_type>(*this); | ^~~~~~~~~~ q2.hpp:56:25: error: ‘value_type’ does not name a type 56 | static_cast<value_type>(*this) = move(other); | ^~~~~~~~~~ q2.hpp: In member function ‘q2::sso_optional<T, N>::operator bool() const’: q2.hpp:61:32: error: ‘value_type’ does not name a type 61 | return static_cast<value_type>(*this) != N; | ^~~~~~~~~~ q2.hpp: In member function ‘bool q2::sso_optional<T, N>::operator==(const q2::sso_optional<T, N>&) const’: q2.hpp:81:29: error: ‘value_type’ does not name a type 81 | if (static_cast<value_type>(*this) == N && other == N || (static_cast<value_type>(*this) != N && other != N && static_cast<value_type>(*this) == other)) { | ^~~~~~~~~~ q2.hpp:81:83: error: ‘value_type’ does not name a type 81 | if (static_cast<value_type>(*this) == N && other == N || (static_cast<value_type>(*this) != N && other != N && static_cast<value_type>(*this) == other)) { | ^~~~~~~~~~ q2.hpp:81:136: error: ‘value_type’ does not name a type 81 | if (static_cast<value_type>(*this) == N && other == N || (static_cast<value_type>(*this) != N && other != N && static_cast<value_type>(*this) == other)) { | ```