Based on this thread http://www.cplusplus.com/forum/general/143019/ I could realize my delegate factory, which is working fine. Now it's time to embed those delegates to my IOC Container.
The IOC Container uses a nested wrapper (based on same concept as the delegates) to reference my delegates or instances (if singletons are required) and have to return the requested object on request:
template <typename T, typename ... ARGS>
inline std::shared_ptr<T> brIOCContainer::resolve(ARGS&& ... args) const
{
std::type_index type = typeid(T);
if(std::is_abstract<T>::value){
std::string msg = "[brIOCContainer]:resolve: Cant resolve object of abstract type: ";
msg.append(brStringUtils::demangle(type.name()));
throw brRegistrationException(msg);
}
auto iter = this->find(type);
if(iter==m_repository.end()){
std::string msg = "[brIOCContainer]:resolve: No entry found for requested class type: ";
msg.append(brStringUtils::demangle(type.name()));
throw brRegistrationException(msg);
}
auto resolver = (iter->second)->getResolver();
return resolver->resolve<T, ARGS...>(std::forward<ARGS>(args)...);
}
The issue occurs in line 21 of the Resolver snipped. The forwarding of the arguments fails with follwoing output:
In file included from D:/tmp/test/modules/brCore/branches/refactor/include/brCore/brApplication.h:38:0,
from d:/tmp/test/modules/brCore/branches/refactor/src/brApplication.cpp:25:
D:/tmp/test/modules/brCore/branches/refactor/include/brCore/brIOCContainer.h: In member function 'std::shared_ptr<_Tp1> binrev::brCore::brIOCContainer::Resolver::resolve(ARGS&& ...) const':
D:/tmp/test/modules/brCore/branches/refactor/include/brCore/brIOCContainer.h:208:15: error: expected primary-expression before '...' token
rs.run<ARGS...>(std::forward<ARGS>(args)...);
^
D:/tmp/test/modules/brCore/branches/refactor/include/brCore/brIOCContainer.h:208:15: error: expected ';' before '...' token
make[2]: *** [CMakeFiles/brCore.dir/src/brApplication.cpp.obj] Error 1
make[1]: *** [CMakeFiles/brCore.dir/all] Error 2
But why? I've tested multiple forwards with this simple code and this works as expected:
The compiler has not seen the declaration of the member function run() (during phase one of the two phase look up) and proceeds on the assumption that run() is not a template.
Unless you announce that you expect it to be a template.
This solves the problem... I've seen this kind of announce in some posts, but never understand why I should use this and when. Thanks a lot!
I would learn to understand why the compiler has lost the declaration of the member function. Could you give me more details or a link, describing the look up mechanism please? Thanks in advance.
When the name of a member template specialization appears after . or -> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object expression of the postfix-expression is type-dependent or the nested-name-specifier in the qualified-id refers to a dependent type, but the name is not a member of the current instantiation, the member template name must be prefixed by the keyword template.
Otherwise the name is assumed to name a non-template.
[Example:
1 2 3 4 5 6 7 8 9 10 11 12 13
struct X {
template<std::size_t> X* alloc();
template<std::size_t> static X* adjust();
};
template<class T> void f(T* p) {
T* p1 = p->alloc<200>(); // ill-formed: < means less than
T* p2 = p->template alloc<200>(); // OK: < starts template argument list
T::adjust<100>(); // ill-formed: < means less than
T::template adjust<100>(); // OK: < starts template argument list
}