Repository: eclipse-iceoryx/iceoryx (C++)

Issue:
Replace `operator std::string()` with `toStdString()` method
## Brief feature description

Replace `operator std::string()` with either `toStdString()` method to make it more verbose or a `toStdString()` free function.

See:
```cpp
auto bla1 = myCxxString.toStdString(); // proposal 1
auto bla2 = std::string(myCxxString.c_str()); // old style, maybe sufficient
auto bla3 = toStdString(myCxxString); // proposal 2

auto bla4 = myCxxString; // will be forbidden
```

Another awesome approach would be to declare a free template function called `into` which can be specialized for any arbitrary types internally or used by users to perform conversions. This would be a way to support explicit conversions with free functions.

See:
```cpp
namespace iox {
// defined maybe in cxx/type_traits.hpp
template<typename Source, typename Destination>
Destination into(const Source& source);
}

// defined in an header
template<>
string<100> iox::into(const std::string& source);

// implemented in cpp file 
```

This approach would not allow us to convert arbitrary strings but we could use it for the most common string aliases like `IdString` etc. But if we have multiple string aliases with the same length we would get a ambiguity error in the linker.
If we put some brains into it we maybe solve the issue and would have a universal conversion idiom in iceoryx.

## Important note

This could also solve the issue we currently have in `cxx::convert` that were we are unable to partially overload `fromString` so that we could convert all `cxx::string`s.
At the moment the conversion has to be explicitly implemented for every string capacity.

Due to a lossy conversion with truncation to the capacity of the fixed string, it should be visible to the user that this might happen and the user must be given the choice to prevent the truncation.

This can be achieved by the following API
- [x] `iox::string<N> into<iox::lossy<iox::string<N>>>(std::string)`
- [x] `iox::optional<iox::string<N>> into<iox::optional<iox::string<N>>>(std::string)`
    - commit [bf168d1](https://github.com/eclipse-iceoryx/iceoryx/pull/1889/commits/bf168d1242b41e4863a4b9f5a2dd73cef335939c) needs to be reverted and additional tests are required

Extracted from: #1196 


Discussion: @elfenpiff we already have `from` and `into` in `helplets.hpp`. The user just has to implement `from` and `into` is already defined for all types which have `from`. See #992. The reason to use this patter was mainly because `enums` do not have conversion operators.

If we don't do implicit conversion, the approach with the method might be the next best idiomatic solution. I think the specialized free function is the worst solution since it is the least discoverable and it is only used for strings. `from`/`into` are a bit better since it would be generic over types but still it is not idiomatic C++.

If we want to go with the `from`/`into` approach for all types, maybe we can have a generic implementation for all types which have a conversion operator to have a common mechanism even for classes which are not under our control.
@elBoberido The `from`/`into` approach would be my preferred way the problem is that we are unable to partially overload the template so that we have a unified way to convert from `std::string` to `cxx::string<N>` ... But I think this should be solvable with some dirty template tricks ;) 
@elfenpiff I'm fine with that
Hi I would like to contribute to this issue as a first time contributor. So are you saying that I should create a separate method that converts variable to a string? 
@NNatarajan0717 that sounds great we are looking forward to it!

So now to the nasty details, in `helplets.hpp` we have already implemented:
```cxx
template <typename F, typename T>
constexpr T from(const F value) noexcept;
```

The idea is that the user provides additional implementations for whatever types they would like to cast and if a fitting implementation is available `from` works otherwise we get a failure.

The problem now is that this is a free function and free functions do not support partially specialized templates. But we would love to have it, so the idea is the following:

```cxx
template<typename Source, typename Destination>
struct From;

template<typename F, typename T>
constexpr T from(const F value) noexcept {
  From<F, T>::from(value); // just forwarding to the struct
}

// then the user can implement a partial specialization for cxx::string like:
template<uint64_t N>
struct From<cxx::string<N>, std::string> {
  static from(const cxx::string<N> & value) { // do stuff
}
```

I hope I drafted the idea sufficiently. Would you be confident to start with this our is something unclear? then I would dive deeper into it!



I will do my best!
@NNatarajan0717 do not hesitate to ask for support when you are stuck. Try out iceoryx on gitter, here you may get an answer even faster. https://gitter.im/eclipse/iceoryx 
Reopening it due to [this](https://github.com/eclipse-iceoryx/iceoryx/pull/1784#discussion_r1068727683) comment to make it more visible to the user that `into<iox::string>` might truncate the result.



Fix (patch):
diff --git a/doc/website/release-notes/iceoryx-unreleased.md b/doc/website/release-notes/iceoryx-unreleased.md
index de1262bcaa..ec1ea15180 100644
--- a/doc/website/release-notes/iceoryx-unreleased.md
+++ b/doc/website/release-notes/iceoryx-unreleased.md
@@ -1003,10 +1003,12 @@
     #include "iceoryx_dust/cxx/std_string_support.hpp"
 
     std::string myStdString("foo");
-    // std::string to iox::string
-    iox::string<3> myIoxString = iox::into<iox::lossy<iox::string<3>>>(myStdString);
+    // std::string to iox::string with truncation when source string exceeds capacity
+    auto myIoxString = iox::into<iox::lossy<iox::string<3>>>(myStdString); // returns a 'iox::string<3>'
+    // std::string to iox::string with fallible conversion when source string exceeds capacity
+    auto maybeMyIoxString = iox::into<iox::optional<iox::string<3>>>(myStdString); // returns a 'iox::optional<iox::string<3>>'
     // iox::string to std::string
-    std::string myConvertedIoxString = iox::into<std::string>(myIoxString);
+    auto myConvertedIoxString = iox::into<std::string>(myIoxString); // returns a 'std::string'
     ```
 
 44. In order to use the comparison or `operator<<` operators, `insert`, `find`, `unsafe_append` functions for
diff --git a/iceoryx_dust/include/iceoryx_dust/cxx/std_string_support.hpp b/iceoryx_dust/include/iceoryx_dust/cxx/std_string_support.hpp
index f982b5600c..a3011dfaa6 100644
--- a/iceoryx_dust/include/iceoryx_dust/cxx/std_string_support.hpp
+++ b/iceoryx_dust/include/iceoryx_dust/cxx/std_string_support.hpp
@@ -17,6 +17,7 @@
 #define IOX_DUST_STD_STRING_SUPPORT_HPP
 
 #include "iox/into.hpp"
+#include "iox/optional.hpp"
 #include "iox/string.hpp"
 
 #include <ostream>
@@ -65,6 +66,12 @@ struct FromImpl<std::string, string<N>>
     static string<N> fromImpl(const std::string& value) noexcept;
 };
 
+template <uint64_t N>
+struct FromImpl<std::string, optional<string<N>>>
+{
+    static optional<string<N>> fromImpl(const std::string& value) noexcept;
+};
+
 template <uint64_t N>
 struct FromImpl<std::string, lossy<string<N>>>
 {
diff --git a/iceoryx_dust/include/iceoryx_dust/internal/cxx/std_string_support.inl b/iceoryx_dust/include/iceoryx_dust/internal/cxx/std_string_support.inl
index 9fbdbea62a..fd326a7334 100644
--- a/iceoryx_dust/include/iceoryx_dust/internal/cxx/std_string_support.inl
+++ b/iceoryx_dust/include/iceoryx_dust/internal/cxx/std_string_support.inl
@@ -32,10 +32,24 @@ inline string<N> FromImpl<std::string, string<N>>::fromImpl(const std::string&)
     static_assert(always_false_v<std::string> && always_false_v<string<N>>, "\n \
         The conversion from 'std::string' to 'iox::string<N>' is potentially lossy!\n \
         This happens when the size of source string exceeds the capacity of the destination string!\n \
-        Please use 'iox::into<iox::lossy<iox::string<N>>>' which returns a 'iox::string<N>' and truncates the\n \
+        Please use either: \n \
+          - 'iox::into<iox::optional<iox::string<N>>>' which returns a 'iox::optional<iox::string<N>>'\n \
+            with a 'nullopt' if the size of the source string exceeds the capacity of the destination string\n \
+          - 'iox::into<iox::lossy<iox::string<N>>>' which returns a 'iox::string<N>' and truncates the\n \
             source string if its size exceeds the capacity of the destination string");
 }
 
+template <uint64_t N>
+inline optional<string<N>> FromImpl<std::string, optional<string<N>>>::fromImpl(const std::string& value) noexcept
+{
+    const auto stringLength = value.size();
+    if (stringLength <= N)
+    {
+        return string<N>(TruncateToCapacity, value.c_str(), stringLength);
+    }
+    return nullopt;
+}
+
 template <uint64_t N>
 inline string<N> FromImpl<std::string, lossy<string<N>>>::fromImpl(const std::string& value) noexcept
 {