<commit_before>Generic Services
================

This section shows you how to create your own generic service class just like `kgr::Service` or `kgr::SingleService`. It's the most advanced part of this documentation. Luckily, you won't have to do it very often.

Well... Let's dive into it shall we?

First, our generic service usually have two template parameter: The sevice class and a dependency class.

    template<typename Type, typename Deps = Dependency<>>

## Option 1: 100% custom implementation

There's nothing to prevent you from reinventing the wheel, as long as the generic definition implement `forward` and `construct` correctly. Good luck.

## Option 2: Extend `kgr::GenericService`

How to use `kgr::GenericService`?
We need to pass it three parameters:

 * The first one is the struct itself. Yes, it's the [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).
 * The second one is what type the generic service should contain. It can be the service, or a pointer to the service or whatever you want.
 * The third one are the dependencies.
 
    template<typename Type, typename Deps = kgr::Dependency<>>
    struct MyGeneric : kgr::GenericService<Service<Type, Deps>, Type, Deps> {
        
    };

Next, we need to use the alias `Self` inside the `GenericService` and use the constructor: 
 
    template<typename Type, typename Deps = kgr::Dependency<>>
    struct MyGeneric : GenericService<Service<Type, Deps>, std::unique_ptr<Type>, Deps> {
        private: using Parent = GenericService<Service<Type, Deps>, std::unique_ptr<Type>, Deps>;
    
    public:
        using typename Parent::Self;
        using Parent::Parent;
    };
    
Then, we must implement two method: `makeService` and `forward`.
Forward is the same forward as we know. However, `makeService` is something new. What is it? It's a static function that takes anything as parameter and return a fully constructed definition.

### Full example
 
    template<typename Type, typename Deps = kgr::Dependency<>>
    struct MyGeneric : GenericService<Service<Type, Deps>, std::unique_ptr<Type>, Deps> {
        private: using Parent = GenericService<Service<Type, Deps>, std::unique_ptr<Type>, Deps>;
    
    public:
        using typename Parent::Self;
        using Parent::Parent;
        
        template<typename... Args>
        static Self makeService(Args&&... args) {
            return Self{ new Type{std::forward<Args>(args)...} };
        }

        std::unique_ptr<Type> forward() {
            return std::move(this->getInstance());
        }
    };
    
#### Singles

If the generic definition should be single, simply make it extending from `kgr::Single` and making `forward` virtual.

[Next chapiter](section8_structure.md)<commit_msg>section doc revision<commit_after>Generic Services
================

This section shows you how to create your own generic service class just like `kgr::Service` or `kgr::SingleService`. It's the most advanced part of this documentation. Luckily, you won't have to do it very often.

Well... Let's dive into it, shall we?

First, our generic service usually have two template parameter: The sevice class and a dependency class.

    template<typename Type, typename Deps = Dependency<>>

## Option 1: 100% custom implementation

There's nothing that prevents you from reinventing the wheel, as long as the generic definition implements `forward` and `construct` correctly. Good luck.

## Option 2: Extend `kgr::GenericService`

How to use `kgr::GenericService`?
We need to pass it three parameters:

 * The first one is the struct itself. Yes, it's the [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).
 * The second one is what type the generic service should contain. It can be the service, or a pointer to the service or anything you want.
 * The third one are the dependencies.
 
    template<typename Type, typename Deps = kgr::Dependency<>>
    struct MyGeneric : kgr::GenericService<Service<Type, Deps>, Type, Deps> {
        
    };

Next, we need to use the alias `Self` inside the `GenericService` and use the constructor: 
 
    template<typename Type, typename Deps = kgr::Dependency<>>
    struct MyGeneric : GenericService<Service<Type, Deps>, std::unique_ptr<Type>, Deps> {
        private: using Parent = GenericService<Service<Type, Deps>, std::unique_ptr<Type>, Deps>;
    
    public:
        using typename Parent::Self;
        using Parent::Parent;
    };
    
Then, we must implement two method: `makeService` and `forward`.
Forward is the same forward as we know. However, `makeService` is something new. What is it? It's a static function that takes anything as parameter and returns a fully constructed definition.

### Full example
 
    template<typename Type, typename Deps = kgr::Dependency<>>
    struct MyGeneric : GenericService<Service<Type, Deps>, std::unique_ptr<Type>, Deps> {
        private: using Parent = GenericService<Service<Type, Deps>, std::unique_ptr<Type>, Deps>;
    
    public:
        using typename Parent::Self;
        using Parent::Parent;
        
        template<typename... Args>
        static Self makeService(Args&&... args) {
            return Self{ new Type{std::forward<Args>(args)...} };
        }

        std::unique_ptr<Type> forward() {
            return std::move(this->getInstance());
        }
    };
    
#### Singles

If the generic definition should be single, simply make it extend the `kgr::Single` struct and make `forward` virtual.

[Next chapiter](section8_structure.md)
{'fraction_non_alphanumeric': 0.10439956725567977, 'fraction_numerical': 0.002163721601153985, 'mean_word_length': 3.7329351535836177, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 55, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2229519', 'n_tokens_mistral': 1511, 'n_tokens_neox': 1455, 'n_words': 600}