Git Product home page Git Product logo

Comments (13)

poletti-marco avatar poletti-marco commented on May 22, 2024

from fruit.

IrisPeter avatar IrisPeter commented on May 22, 2024

I was hoping that it would be possible somehow to avoid polluting IRepository with any methods that don't look like generalised database retrieval and update methods.

SetBackingStore would be called when setting up the unit test, so it would need to be called before anyone called any of the methods of IRepository

I'm not quite sure what you were getting at with your two references, but in your Server example which uses providers I see something interesting in worker_thread_main which might be something related to what I need. When creating the injector for the RequestDispatcher you pass the Request object to it, and it seems that having the getRequest method as the 2nd parameter to the injector, and a pointer to the request argument, makes a call to .bindinstance which means that when FooHandlerImpl is created by injection it receives a reference to that original Request object.

static void worker_thread_main(const NormalizedComponent<Required<Request>, RequestDispatcher>& requestDispatcherNormalizedComponent, Request request)
{
	Injector<RequestDispatcher> injector(requestDispatcherNormalizedComponent, getRequestComponent, &request);

	RequestDispatcher* requestDispatcher(injector);
	requestDispatcher->handleRequest();
}

I also see something similar happening when setting up the NormalizedComponent.

I've noticed in these repositories that come from C# that a repository usually has a context variable in this case DbContext from EntityFramework:

public class Repository<TEntity> : IRepository <TEntity> where TEntity : class
{
      protected readonly DbContext Context;
      protected readonly DbSet<TEntity> Entities;

      public Repository(DbContext context)
      {
          Context = context;
          Entities = Context.Set<TEntity>();
      }

      public void Add(TEntity entity)
      {
          Entities.Add(entity);
      }
}

Upon seeing this I asked ChatGPT about other context objects that other frameworks might use in their repositories and it referred to objects from ADO.NET and NHibernate. As in the above example they receive one of these contexts via DI in their constructors.

The different context objects are much more fully featured than anything I might need, I think that I would only need a std::string to represent the JSON object that would allow the repository to return an object.

For my requirements it is only the JSON version of the repository that needs a context object, as all the DB implementations would just feature one of our special DAO objects and they are able to retrieve the DB connections/strings without being explicitly stated.

I imagine that both repositories will need to have context objects passed to their constructors, the string would just be empty for the DB repositories.

I would imagine I would probably do the same thing as you do in the example where the string lives as a member of some struct, say JsonContext or maybe I would just call it DbContext, I'm not sure what would make sense to readers of any finished code I might come up with.

I find certain parts of the Fruit library hard to get my head around, so even though I have stepped through the Server example I still require some guidance on how I can get this to work.

from fruit.

poletti-marco avatar poletti-marco commented on May 22, 2024

Could you pass the backing store as a param to getScalerTestComponent and use bindInstance() there?
Something like:

class JSONScalerRepositoryImpl : public IScalerRepository
{
private:
  std::string& backingStore;
public:
   INJECT(JSONScalerRepositoryImpl(std::string& backingStore)) : backingStore(backingStore) {};
   ...
};
fruit::Component<ScalerFactory> getScalerTestComponent(std::string& backingStore)
{
    return fruit::createComponent()
        .bindInstance(backingStore)
        // Note: order matters here. This replace().with() must be before the install. Otherwise Fruit will report the
        // wrong order as a run-time error.
        .replace(getScalerRepositoryDB).with(getScalerJsonRepository)
        .install(getScalerComponent);
}
std::string backingStore = ...;
Injector<ScalerFactory> underTestInjector(getScalerTestComponent, backingStore);

from fruit.

IrisPeter avatar IrisPeter commented on May 22, 2024

The modifications to Testing.cpp are compiling OK.

However when I try and compile JSONScalerRepository.cpp I receive the following compilation errors:

1>------ Build started: Project: RepositoryExample, Configuration: Debug x64 ------
1>Scanning sources for module dependencies...
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\injection_errors.h(33,33): error C2338: static_assert failed: 'No explicit binding nor C::Inject definition was found for T.'
1>  static_assert(AlwaysFalse<T>::value, "No explicit binding nor C::Inject definition was found for T.");
1>                                ^ (compiling source file 'JSONScalerRepository.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\injection_errors.h(33,33):
1>    the template instantiation context (the oldest one first) is
1>      static_assert(AlwaysFalse<T>::value, "No explicit binding nor C::Inject definition was found for T.");
1>                                    ^
1>        C:\Dev\VisualStudio Projects\Visual Studio 2022\Projects\C++\Examples\Fruit\RepositoryAttempts\WithBackingStore-RepositoryExample\JSONScalerRepository.cpp(41,2):
1>        see reference to function template instantiation 'fruit::Component<IScalerRepository>::Component<fruit::impl::Bind<IScalerRepository,JSONScalerRepositoryImpl>>(fruit::PartialComponent<fruit::impl::Bind<IScalerRepository,JSONScalerRepositoryImpl>> &&) noexcept' being compiled
1>        	return fruit::createComponent().bind<IScalerRepository, JSONScalerRepositoryImpl>();
1>        	^
1>            C:\Dev\VisualStudio Projects\Visual Studio 2022\Projects\C++\Examples\Fruit\RepositoryAttempts\WithBackingStore-RepositoryExample\JSONScalerRepository.cpp(41,2):
1>            see the first reference to 'fruit::Component<IScalerRepository>::Component' in 'getScalerRepositoryJSONComponent'
1>            	return fruit::createComponent().bind<IScalerRepository, JSONScalerRepositoryImpl>();
1>            	^
1>        C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(56,59):
1>        see reference to class template instantiation 'fruit::impl::NoBindingFoundError<Context>' being compiled
1>          (void)typename fruit::impl::meta::CheckIfError<Op>::type();
1>                                                                  ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C2039: 'Result': is not a member of 'fruit::impl::meta::Error<ErrorTag,Context>'
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C2039:         with
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C2039:         [
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C2039:             ErrorTag=fruit::impl::NoBindingFoundErrorTag
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C2039:         ]
1>      fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(typename Op::Result)>>::type();
1>                                                                                ^ (compiling source file 'JSONScalerRepository.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\basics.h(63,8):
1>    see declaration of 'fruit::impl::meta::Error<ErrorTag,Context>'
1>        with
1>        [
1>            ErrorTag=fruit::impl::NoBindingFoundErrorTag
1>        ]
1>    struct Error {};
1>           ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>      fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(typename Op::Result)>>::type();
1>                                                                                ^ (compiling source file 'JSONScalerRepository.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(954,47): error C2825: 'Comp': must be a class or namespace when followed by '::'
1>    using Loop = ProofForestFindLoop(typename Comp::Deps);
1>                                              ^ (compiling source file 'JSONScalerRepository.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(954,47):
1>    the template instantiation context (the oldest one first) is
1>        using Loop = ProofForestFindLoop(typename Comp::Deps);
1>                                                  ^
1>        C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,26):
1>        see reference to alias template instantiation 'fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(int)>' being compiled
1>              fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(typename Op::Result)>>::type();
1>                                 ^
1>        C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(253,41):
1>        see reference to class template instantiation 'fruit::impl::meta::DoEval<fruit::impl::meta::CheckNoLoopInDeps (int)>' being compiled
1>        using Eval = typename DoEval<MetaExpr>::type;
1>                                                ^
1>        C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76):
1>        see reference to class template instantiation 'fruit::impl::meta::CheckNoLoopInDeps::apply<MetaExpr>' being compiled
1>        with
1>        [
1>            MetaExpr=int
1>        ]
1>              MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                                   ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(954,53): error C2510: 'Comp': left of '::' must be a class/struct/union
1>    using Loop = ProofForestFindLoop(typename Comp::Deps);
1>                                                    ^ (compiling source file 'JSONScalerRepository.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(954,53): error C2061: syntax error: identifier 'Deps'
1>    using Loop = ProofForestFindLoop(typename Comp::Deps);
1>                                                    ^ (compiling source file 'JSONScalerRepository.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(955,21): error C2226: syntax error: unexpected type 'fruit::impl::meta::IsNone'
1>    using type = If(IsNone(Loop), Bool<true>, ConstructErrorWithArgVector(SelfLoopErrorTag, Loop));
1>                    ^ (compiling source file 'JSONScalerRepository.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(955,74): error C2059: syntax error: '('
1>    using type = If(IsNone(Loop), Bool<true>, ConstructErrorWithArgVector(SelfLoopErrorTag, Loop));
1>                                                                         ^ (compiling source file 'JSONScalerRepository.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2039: 'type': is not a member of 'fruit::impl::meta::CheckNoLoopInDeps::apply<MetaExpr>'
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2039:         with
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2039:         [
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2039:             MetaExpr=int
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2039:         ]
1>      MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                           ^ (compiling source file 'JSONScalerRepository.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(953,10):
1>    see declaration of 'fruit::impl::meta::CheckNoLoopInDeps::apply<MetaExpr>'
1>        with
1>        [
1>            MetaExpr=int
1>        ]
1>      struct apply {
1>             ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2146: syntax error: missing '>' before identifier 'type'
1>      MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                           ^ (compiling source file 'JSONScalerRepository.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,83): error C2039: 'type': is not a member of '`global namespace''
1>      MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                                  ^ (compiling source file 'JSONScalerRepository.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,83): error C2146: syntax error: missing ';' before identifier 'type'
1>      MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                                  ^ (compiling source file 'JSONScalerRepository.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,83): error C2602: 'fruit::impl::meta::DoEval<fruit::impl::meta::CheckNoLoopInDeps (int)>::type' is not a member of a base class of 'fruit::impl::meta::DoEval<fruit::impl::meta::CheckNoLoopInDeps (int)>'
1>      MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                                  ^ (compiling source file 'JSONScalerRepository.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(100,9):
1>    see declaration of 'fruit::impl::meta::DoEval<fruit::impl::meta::CheckNoLoopInDeps (int)>::type'
1>      using type = typename DoEval<typename std::conditional<
1>            ^
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(93,8):
1>    see declaration of 'fruit::impl::meta::DoEval<fruit::impl::meta::CheckNoLoopInDeps (int)>'
1>    struct DoEval<MetaFun(MetaExprs...)> {
1>           ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,92): error C2955: 'fruit::impl::meta::CheckIfError': use of class template requires template argument list
1>      fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(typename Op::Result)>>::type();
1>                                                                                           ^ (compiling source file 'JSONScalerRepository.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\errors.h(28,8):
1>    see declaration of 'fruit::impl::meta::CheckIfError'
1>    struct CheckIfError {
1>           ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(63,76): error C2039: 'numEntries': is not a member of 'fruit::impl::meta::Error<ErrorTag,Context>'
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(63,76): error C2039:         with
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(63,76): error C2039:         [
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(63,76): error C2039:             ErrorTag=fruit::impl::NoBindingFoundErrorTag
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(63,76): error C2039:         ]
1>  std::size_t num_entries = partial_component.storage.numBindings() + Op().numEntries();
1>                                                                           ^ (compiling source file 'JSONScalerRepository.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\basics.h(63,8):
1>    see declaration of 'fruit::impl::meta::Error<ErrorTag,Context>'
1>        with
1>        [
1>            ErrorTag=fruit::impl::NoBindingFoundErrorTag
1>        ]
1>    struct Error {};
1>           ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(66,5): error C2064: term does not evaluate to a function taking 1 arguments
1>  Op()(entries);
1>    ^ (compiling source file 'JSONScalerRepository.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(51,100): error C1907: unable to recover from previous error(s); stopping compilation
1>inline Component<Params...>::Component(PartialComponent<Bindings...>&& partial_component) noexcept : storage() {
1>                                                                                                   ^ (compiling source file 'JSONScalerRepository.cpp')
1>JSONScalerRepository.cpp
1>Done building project "RepositoryExample.vcxproj" -- FAILED.

main.cpp I am receiving the following compilation errors:

1>------ Build started: Project: RepositoryExample, Configuration: Debug x64 ------
1>Scanning sources for module dependencies...
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component_install_arg_checks.defn.h(34,13): error C2440: 'initializing': cannot convert from 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>' to 'std::string &'
1>        T x2(std::move(value));
1>            ^ (compiling source file 'RepositoryExample.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component_install_arg_checks.defn.h(34,13):
1>    A non-const reference may only be bound to an lvalue
1>            T x2(std::move(value));
1>                ^
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component_install_arg_checks.defn.h(34,13):
1>    the template instantiation context (the oldest one first) is
1>            T x2(std::move(value));
1>                ^
1>        C:\Dev\VisualStudio Projects\Visual Studio 2022\Projects\C++\Examples\Fruit\RepositoryAttempts\RepositoryExample\RepositoryExample.cpp(159,53):
1>        see reference to function template instantiation 'fruit::Injector<ScalerFactory>::Injector<std::string&,std::string&>(fruit::Component<ScalerFactory> (__cdecl *)(std::string &),std::string &)' being compiled
1>            fruit::Injector<ScalerFactory> underTestInjector(getScalerTestComponent, backingStore);
1>                                                            ^
1>            C:\Dev\VisualStudio Projects\Visual Studio 2022\Projects\C++\Examples\Fruit\RepositoryAttempts\RepositoryExample\RepositoryExample.cpp(159,53):
1>            see the first reference to 'fruit::Injector<ScalerFactory>::Injector' in 'scaler_main'
1>                fruit::Injector<ScalerFactory> underTestInjector(getScalerTestComponent, backingStore);
1>                                                                ^
1>        C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\injector.defn.h(30,56):
1>        see reference to function template instantiation 'fruit::PartialComponent<fruit::impl::InstallComponent<fruit::Component<ScalerFactory> (std::string &)>> fruit::PartialComponent<>::install<ScalerFactory,std::string&,std::string&>(fruit::Component<ScalerFactory> (__cdecl *)(std::string &),std::string &)' being compiled
1>          Component<P...> component = fruit::createComponent().install(getComponent, std::forward<Args>(args)...);
1>                                                               ^
1>        C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(250,38):
1>        see reference to function template instantiation 'int fruit::impl::checkAcceptableComponentInstallArg<std::string&>(void)' being compiled
1>          (void)IntCollector{0, fruit::impl::checkAcceptableComponentInstallArg<FormalArgs>()...};
1>                                             ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component_install_arg_checks.defn.h(38,37): error C2064: term does not evaluate to a function taking 1 arguments
1>        std::size_t h = std::hash<T>()(constRef);
1>                                    ^ (compiling source file 'RepositoryExample.cpp')
1>RepositoryExample.cpp
1>Done building project "RepositoryExample.vcxproj" -- FAILED.

JSONScalerRepository.cpp

#include "JSONScalerRepository.h"

class JSONScalerRepositoryImpl : public IScalerRepository
{
private:
  std::string& backingStore;
public:
   INJECT(JSONScalerRepositoryImpl(std::string& backingStore)) : backingStore(backingStore) {};

	//INJECT(JSONScalerRepositoryImpl()) = default;

	scaler GetByKey(const key& theKey = {}) override
	{
		std::println("GetByKey called from the JSON Scaler Repository");
		scaler scale;
		scale.factor = 5.5;

		return scale;
	}

	void Add(const scaler& item) override
	{
	}

	void Update(const scaler& item) override
	{
	}

	void Remove(const scaler& key) override
	{
	}

};

fruit::Component<IScalerRepository> getScalerRepositoryJSONComponent()
{
	return fruit::createComponent().bind<IScalerRepository, JSONScalerRepositoryImpl>();
}

from fruit.

IrisPeter avatar IrisPeter commented on May 22, 2024

I also tried turning the std::string into a struct holding a string like the Request object in the Server example.

That gave slightly different errors, in the main.cpps the main error was inside this bit of the fruit code

template <typename T>
FRUIT_ALWAYS_INLINE inline int checkAcceptableComponentInstallArg() {
    // This lambda checks that the required operations on T exist.
    // Note that the lambda is never actually executed.
    auto checkRequirements = [](const T& constRef, T value) {
        T x1(constRef);
        T x2(std::move(value));
        x1 = constRef;
        x2 = std::move(value);
        bool b = (constRef == constRef);
        std::size_t h = std::hash<T>()(constRef);
        (void)x1;
        (void)x2;
        (void)b;
        (void)h;
    };
    (void)checkRequirements;
    return 0;
}

Its the std::move line when using std::string, and the x1 = constRef; line if the Context struct.

Inside JSONScalerRepository.cpp its the following code that fails:

1>        C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(56,59):
1>        see reference to class template instantiation 'fruit::impl::NoBindingFoundError<Context>' being compiled
1>          (void)typename fruit::impl::meta::CheckIfError<Op>::type();
1>                                                                  ^

The only thing that changes is that Context in the code we started with was 1> see declaration of 'fruit::impl::meta::Error<ErrorTag,std::basic_string<char,std::char_traits<char>,std::allocator<char>>>'

I'm not sure what is going on, as it doesn't seem that different to the Server example.

from fruit.

IrisPeter avatar IrisPeter commented on May 22, 2024

I wondered whether the return type of both getScalerRepositoryDB and getScalerJsonRepository needed to be changed to:

fruit::Component<fruit::Required<std::string>, IScalerRepository> getScalerJsonRepository();
fruit::Component<fruit::Required<std::string>, IScalerRepository> getScalerRepositoryDBComponent();

and whilst that seemed to fix the compiling of JSONScalerRepository.cpp, it seemed to break compiling Scaler.cpp.

Also whilst Testing.cpp compiled OK with getScalerTestComponent having std::string& backingStore as its parameter, the creation of the injector in main.cpp did not like it, but when I changed the parameter to std::string backingStore, then it was OK with the change, but I was still left with Scaler.cpp not compiling with the following error:

1>Scanning sources for module dependencies...
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\injection_errors.h(33,33): error C2338: static_assert failed: 'No explicit binding nor C::Inject definition was found for T.'
1>  static_assert(AlwaysFalse<T>::value, "No explicit binding nor C::Inject definition was found for T.");
1>                                ^ (compiling source file 'Scaler.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\injection_errors.h(33,33):
1>    the template instantiation context (the oldest one first) is
1>      static_assert(AlwaysFalse<T>::value, "No explicit binding nor C::Inject definition was found for T.");
1>                                    ^
1>        C:\Dev\VisualStudio Projects\Visual Studio 2022\Projects\C++\Examples\Fruit\RepositoryAttempts\RepositoryExample\Scaler.cpp(46,5):
1>        see reference to function template instantiation 'fruit::Component<ScalerFactory>::Component<fruit::impl::InstallComponent<fruit::Component<fruit::Required<std::string>,IScalerRepository> (void)>,fruit::impl::Bind<Scaler,ScalerImpl>>(fruit::PartialComponent<fruit::impl::InstallComponent<fruit::Component<fruit::Required<std::string>,IScalerRepository> (void)>,fruit::impl::Bind<Scaler,ScalerImpl>> &&) noexcept' being compiled
1>            return createComponent().bind<Scaler, ScalerImpl>().install(getScalerRepositoryDBComponent);
1>            ^
1>            C:\Dev\VisualStudio Projects\Visual Studio 2022\Projects\C++\Examples\Fruit\RepositoryAttempts\RepositoryExample\Scaler.cpp(46,5):
1>            see the first reference to 'fruit::Component<ScalerFactory>::Component' in 'getScalerComponent'
1>                return createComponent().bind<Scaler, ScalerImpl>().install(getScalerRepositoryDBComponent);
1>                ^
1>        C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(56,59):
1>        see reference to class template instantiation 'fruit::impl::NoBindingFoundError<std::basic_string<char,std::char_traits<char>,std::allocator<char>>>' being compiled
1>          (void)typename fruit::impl::meta::CheckIfError<Op>::type();
1>                                                                  ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C2039: 'Result': is not a member of 'fruit::impl::meta::Error<ErrorTag,std::basic_string<char,std::char_traits<char>,std::allocator<char>>>'
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C2039:         with
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C2039:         [
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C2039:             ErrorTag=fruit::impl::NoBindingFoundErrorTag
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C2039:         ]
1>      fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(typename Op::Result)>>::type();
1>                                                                                ^ (compiling source file 'Scaler.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\basics.h(63,8):
1>    see declaration of 'fruit::impl::meta::Error<ErrorTag,std::basic_string<char,std::char_traits<char>,std::allocator<char>>>'
1>        with
1>        [
1>            ErrorTag=fruit::impl::NoBindingFoundErrorTag
1>        ]
1>    struct Error {};
1>           ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,81): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>      fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(typename Op::Result)>>::type();
1>                                                                                ^ (compiling source file 'Scaler.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(954,47): error C2825: 'Comp': must be a class or namespace when followed by '::'
1>    using Loop = ProofForestFindLoop(typename Comp::Deps);
1>                                              ^ (compiling source file 'Scaler.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(954,47):
1>    the template instantiation context (the oldest one first) is
1>        using Loop = ProofForestFindLoop(typename Comp::Deps);
1>                                                  ^
1>        C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,26):
1>        see reference to alias template instantiation 'fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(int)>' being compiled
1>              fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(typename Op::Result)>>::type();
1>                                 ^
1>        C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(253,41):
1>        see reference to class template instantiation 'fruit::impl::meta::DoEval<fruit::impl::meta::CheckNoLoopInDeps (int)>' being compiled
1>        using Eval = typename DoEval<MetaExpr>::type;
1>                                                ^
1>        C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76):
1>        see reference to class template instantiation 'fruit::impl::meta::CheckNoLoopInDeps::apply<MetaExpr>' being compiled
1>        with
1>        [
1>            MetaExpr=int
1>        ]
1>              MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                                   ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(954,53): error C2510: 'Comp': left of '::' must be a class/struct/union
1>    using Loop = ProofForestFindLoop(typename Comp::Deps);
1>                                                    ^ (compiling source file 'Scaler.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(954,53): error C2061: syntax error: identifier 'Deps'
1>    using Loop = ProofForestFindLoop(typename Comp::Deps);
1>                                                    ^ (compiling source file 'Scaler.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(955,21): error C2226: syntax error: unexpected type 'fruit::impl::meta::IsNone'
1>    using type = If(IsNone(Loop), Bool<true>, ConstructErrorWithArgVector(SelfLoopErrorTag, Loop));
1>                    ^ (compiling source file 'Scaler.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(955,74): error C2059: syntax error: '('
1>    using type = If(IsNone(Loop), Bool<true>, ConstructErrorWithArgVector(SelfLoopErrorTag, Loop));
1>                                                                         ^ (compiling source file 'Scaler.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2039: 'type': is not a member of 'fruit::impl::meta::CheckNoLoopInDeps::apply<MetaExpr>'
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2039:         with
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2039:         [
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2039:             MetaExpr=int
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2039:         ]
1>      MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                           ^ (compiling source file 'Scaler.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\component.h(953,10):
1>    see declaration of 'fruit::impl::meta::CheckNoLoopInDeps::apply<MetaExpr>'
1>        with
1>        [
1>            MetaExpr=int
1>        ]
1>      struct apply {
1>             ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,76): error C2146: syntax error: missing '>' before identifier 'type'
1>      MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                           ^ (compiling source file 'Scaler.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,83): error C2039: 'type': is not a member of '`global namespace''
1>      MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                                  ^ (compiling source file 'Scaler.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,83): error C2146: syntax error: missing ';' before identifier 'type'
1>      MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                                  ^ (compiling source file 'Scaler.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(102,83): error C2602: 'fruit::impl::meta::DoEval<fruit::impl::meta::CheckNoLoopInDeps (int)>::type' is not a member of a base class of 'fruit::impl::meta::DoEval<fruit::impl::meta::CheckNoLoopInDeps (int)>'
1>      MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
1>                                                                                  ^ (compiling source file 'Scaler.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(100,9):
1>    see declaration of 'fruit::impl::meta::DoEval<fruit::impl::meta::CheckNoLoopInDeps (int)>::type'
1>      using type = typename DoEval<typename std::conditional<
1>            ^
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\eval.h(93,8):
1>    see declaration of 'fruit::impl::meta::DoEval<fruit::impl::meta::CheckNoLoopInDeps (int)>'
1>    struct DoEval<MetaFun(MetaExprs...)> {
1>           ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(60,92): error C2955: 'fruit::impl::meta::CheckIfError': use of class template requires template argument list
1>      fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(typename Op::Result)>>::type();
1>                                                                                           ^ (compiling source file 'Scaler.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\errors.h(28,8):
1>    see declaration of 'fruit::impl::meta::CheckIfError'
1>    struct CheckIfError {
1>           ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(63,76): error C2039: 'numEntries': is not a member of 'fruit::impl::meta::Error<ErrorTag,std::basic_string<char,std::char_traits<char>,std::allocator<char>>>'
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(63,76): error C2039:         with
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(63,76): error C2039:         [
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(63,76): error C2039:             ErrorTag=fruit::impl::NoBindingFoundErrorTag
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(63,76): error C2039:         ]
1>  std::size_t num_entries = partial_component.storage.numBindings() + Op().numEntries();
1>                                                                           ^ (compiling source file 'Scaler.cpp')
1>    C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\meta\basics.h(63,8):
1>    see declaration of 'fruit::impl::meta::Error<ErrorTag,std::basic_string<char,std::char_traits<char>,std::allocator<char>>>'
1>        with
1>        [
1>            ErrorTag=fruit::impl::NoBindingFoundErrorTag
1>        ]
1>    struct Error {};
1>           ^
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(66,5): error C2064: term does not evaluate to a function taking 1 arguments
1>  Op()(entries);
1>    ^ (compiling source file 'Scaler.cpp')
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(51,100): error C1907: unable to recover from previous error(s); stopping compilation
1>inline Component<Params...>::Component(PartialComponent<Bindings...>&& partial_component) noexcept : storage() {
1>                                                                                                   ^ (compiling source file 'Scaler.cpp')
1>Scaler.cpp
1>Done building project "RepositoryExample.vcxproj" -- FAILED.

from fruit.

poletti-marco avatar poletti-marco commented on May 22, 2024

Oh sorry I forgot the component types had to be the same since you're using replace(...).with(...).
Try this:

fruit::Component<IScalerRepository> getScalerJsonRepository(std::string& jsonString) {
	return fruit::createComponent()
            .bind<IScalerRepository, JSONScalerRepositoryImpl>()
            .bindInstance(jsonString);
}
// As before
fruit::Component<IScalerRepository> getScalerRepositoryDBComponent() {...}
fruit::Component<ScalerFactory> getScalerTestComponent(std::string& jsonString) {
    return fruit::createComponent()
        // Note: order matters here. This replace().with() must be before the install. Otherwise Fruit will report the
        // wrong order as a run-time error.
        .replace(getScalerRepositoryDB).with(getScalerJsonRepository, jsonString)
        .install(getScalerComponent);
}

from fruit.

IrisPeter avatar IrisPeter commented on May 22, 2024

Thanks @poletti-marco ,

I'm further along, I can manage to get the std::string version to compile.

The compiler won't accept your specific changes, I had to remove the & from fruit::Component<ScalerFactory> getScalerTestComponent(std::string& jsonString) and from getScalerJsonRepository otherwise it fails inside checkAcceptableComponentInstallArg again.

In the struct Context version (containing a std::string) I had to add the following inside the struct:

auto operator<=>(const Context&) const = default;

and also outside the struct:

namespace std
{
    template <>
    struct hash<Context>
    {
        size_t operator()(const Context& ctx) const { return std::hash<std::string>()(ctx.BackingStore); }
    };
}

The problem I'm having is that the repository crashes the moment you access the backingStore, at first I didn't get around to referencing the backingStore and so nothing crashed, however the moment I tried to access it we get a crash.

If you modify JSONScalerRepositoryImpl as follows:

class JSONScalerRepositoryImpl : public IScalerRepository
{
private:
  std::string backingStore;
public:
   INJECT(JSONScalerRepositoryImpl(std::string info)) : backingStore(info) {};
       ...

The crash will move to the injection site (an STL member throws when trying to fulfil the constructor.

I then wondered whether the Component functions had to take pointers because the working Server example the function getRequestComponent takes a Request* rather than a 'Request' and then it dereferences the pointer:

static Component<Request> getRequestComponent(Request* request)
{
	return createComponent().bindInstance(*request);
}

When the request is injected at that point in the Server example it does bind as a const Request*.

I tried that modification both in my std::string version and the Context version.

In Context version
Testing.cpp compiles OK
main.cpp errors with Error C2440 'initializing': cannot convert from 'initializer list' to 'std::tuple<Context *>

In std::string version
Testing.cpp errors with Error C2440 'initializing': cannot convert from 'initializer list' to 'std::tuple<std::string>
main.cpp compiles OK

from fruit.

IrisPeter avatar IrisPeter commented on May 22, 2024

Just noticed

In the std::string version I had left the following in Testing.h/cpp:

fruit::Component<ScalerFactory> getScalerTestComponent(std::string)

When I changed that to std::string* the error disappears in Testing.cpp.

from fruit.

IrisPeter avatar IrisPeter commented on May 22, 2024

So now I have a working version with std::string as long as all the parameters are std::string*

The Context version just has the error I showed earlier:

image

1>------ Build started: Project: RepositoryExample, Configuration: Debug x64 ------
1>Scanning sources for module dependencies...
1>C:\Dev\Libraries\fruit-3.7.1\out\install\x64-Debug\Include\fruit\impl\component.defn.h(255,39): error C2440: 'initializing': cannot convert from 'initializer list' to 'std::tuple<Context *>'
1>RepositoryExample.cpp
1>Done building project "RepositoryExample.vcxproj" -- FAILED.

For some reason the fuller error is only showing in the problem details view.

Its confusing why the Context* version doesn't work as the Server example in the Fruit examples is very similar

from fruit.

poletti-marco avatar poletti-marco commented on May 22, 2024

I'm guessing there's a mismatch somewhere.
std::string doesn't have any special handling so if you just replace std::string with Context everywhere that interacts with Fruit then it should still work.
Can you share the parts of the code that reference Context?

from fruit.

IrisPeter avatar IrisPeter commented on May 22, 2024

So now I have a working version with std::string as long as all the parameters are std::string*

The Context version just has the error I showed earlier:

image

For some reason the fuller error is only showing in the problem details view.

Its confusing why the Context* version doesn't work as the Server example in the Fruit examples is very similar

Scratch the above I had forgotten to update the variable passed to the Injector constructor so that it was a Context object rather than a std::string

It's all now working, thanks @poletti-marco

So in summary for anyone who looks at this issue wanting to do something similar, the steps where:

fruit::Component<IScalerRepository> getScalerJsonRepository(std::string* pJsonString) 
{
	return fruit::createComponent()
            .bind<IScalerRepository, JSONScalerRepositoryImpl>()
            .bindInstance(*pJsonString);
}
// As before
fruit::Component<IScalerRepository> getScalerRepositoryDBComponent() {...}
fruit::Component<ScalerFactory> getScalerTestComponent(std::string* pJsonString) 
{
    return fruit::createComponent()
        // Note: order matters here. This replace().with() must be before the install. Otherwise Fruit will report the
        // wrong order as a run-time error.
        .replace(getScalerRepositoryDB).with(getScalerJsonRepository, pJsonString)
        .install(getScalerComponent);
}

and finally

class JSONScalerRepositoryImpl : public IScalerRepository
{
private:
   std::string m_context;
public:
   INJECT(JSONScalerRepositoryImpl(const std::string& json)) : m_context(json) {}
   ...
};

So both the spaceship operator inside Context and the hash implementation were irrelevant, they were only required when the code had a either a plain object or a reference to an object, so I have removed them.

from fruit.

IrisPeter avatar IrisPeter commented on May 22, 2024

Closing Issue due to working instructions in thread

from fruit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.