Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start convert from C# to C++. Issue: https://github.com/linksplatform… #80

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
54 changes: 35 additions & 19 deletions cpp/Platform.Converters/CachingConverterDecorator.h
Original file line number Diff line number Diff line change
@@ -1,41 +1,57 @@
#pragma once
#include <iomanip>
#include <string>

#include <functional>
#include <memory>
#include <unordered_map>


namespace Platform::Converters
{
VasiliyevAD marked this conversation as resolved.
Show resolved Hide resolved
template <typename TSource, typename TTarget, typename TCache = std::unordered_map<TSource, TTarget>> class Cached
{
private: std::function<TTarget(TSource)>& _cachedFunction;

private: TCache& _cache;

public: Cached(std::function<TTarget(TSource)>& cachedFunction, std::unordered_map<TSource, TTarget>& cache) : _cachedFunction(cachedFunction), _cache(cache) {};

public: TTarget operator()(TSource&& source)
{
if (auto cursor = _cache.find(source); cursor != _cache.end())
template<typename TCache, typename TConverter, typename TSource>
auto CachedCall(TCache& cache, TConverter&& converter, TSource&& source)
-> std::add_lvalue_reference_t<std::decay_t<std::invoke_result_t<TConverter, TSource>>> {
if (auto cursor = cache.find(source); cursor != cache.end())
{
return cursor->second;
}
else
{
return *_cache.insert({ source, _baseConverter(source) });
auto target = std::forward<TConverter>(converter)(source);
return cache.insert({ std::forward<TSource>(source), std::move(target) }).first->second;
}
}

public: TTarget operator()(const TSource& source)
template <typename TSource, typename TTarget, typename TCache = std::unordered_map<TSource, TTarget>>
class Cached
{
if (auto cursor = _cache.find(source); cursor != _cache.end())
std::function<TTarget(TSource)> _cachedFunction;
TCache _cache;
public:
Cached(std::function<TTarget(TSource)> cachedFunction)
: _cachedFunction(std::move(cachedFunction)) {};

Cached(std::function<TTarget(TSource)> cachedFunction, TCache cache)
: _cachedFunction(std::move(cachedFunction)), _cache(std::move(cache)) {};

const TTarget& operator()(TSource&& source) &
{
return cursor->second;
return CachedCall(_cache, _cachedFunction, std::move(source));
}
else

const TTarget& operator()(const TSource& source) &
{
return *_cache.insert({ source, _baseConverter(source) });
return CachedCall(_cache, _cachedFunction, source);
}

TTarget&& operator()(TSource&& source) &&
{
return std::move(CachedCall(_cache, _cachedFunction, std::move(source)));
}

TTarget&& operator()(const TSource& source) &&
{
return std::move(CachedCall(_cache, _cachedFunction, source));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TTarget&& operator()(TSource&& source) &&
{
return std::move(CachedCall(_cache, _cachedFunction, std::move(source)));
}
TTarget&& operator()(const TSource& source) &&
{
return std::move(CachedCall(_cache, _cachedFunction, source));
}
TTarget operator()(TSource&& source) &&
{
return _cachedFunction(std::move(source));
}
TTarget operator()(const TSource& source) &&
{
return _cachedFunction(source);
}

}
};
}