Comments (13)
from fruit.
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.
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.
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.
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.
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.
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.
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.
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.
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:
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.
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.
So now I have a working version with
std::string
as long as all the parameters arestd::string*
The
Context
version just has the error I showed earlier:
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.
Closing Issue due to working instructions in thread
from fruit.
Related Issues (20)
- Fruit does not build in Visual Studio Versions 2019, 2022 or 2022 Preview with CMake HOT 8
- what should I do to use a string as an annotion of some bind? HOT 3
- VS2022 Just My Code for Fruit Library fails using CMAKE HOT 6
- Create a fruit::Component by iterating over a list of fruit::Components HOT 7
- Can fruit be used with C language? HOT 2
- Handling lifetimes HOT 6
- Providing non-injected arguments to DI Objects HOT 14
- Build fails with Visual Studio 2022 with C++20 HOT 8
- Fruit with QT HOT 4
- Factories with reference types broken in fruit 3.7.0
- Generic binding? HOT 2
- Defining Factory Functions for Objects with Multiple Constructors HOT 11
- Replace boost HOT 1
- Creating Collections of DI Objects HOT 3
- [Suggestion] ExtractFirstError meta function SHOULD be non-error safe HOT 2
- Can no longer build examples in VS2022 Preview built by Visual Studio, VS CMake builds OK HOT 7
- Examples miss virtual dtor
- bindInstance with copy HOT 13
- Understanding Compiler error messages in Fruit HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fruit.