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)) {
|
```