I know I need a template
keyword when calling a template method of a template in a depended context. This is quite clear to me.
Now, I have something like:
#include <repository/RepositoryManager.hpp>
#include <events/Manager.hpp>
#include <memory>
#include <boost/di.hpp>
namespace di = boost::di;
inline std::shared_ptr<RepositoryManager> createRepositoryManager(int p) {
(void)p;
auto injector = di::make_injector(
di::bind<events::Manager>().to<events::Manager>().in(di::singleton)
);
return injector.create<std::shared_ptr<RepositoryManager>>();
}
This compiles and works as expected but what I actually need is it to be a template but simply changing the definition like this:
template <typename Param>
inline std::shared_ptr<RepositoryManager> createRepositoryManager(Param p)
Gives me a bunch of errors:
In file included from x/main.cpp:7:0:
x/setup.hpp: In function ‘std::shared_ptr<RepositoryManager> createRepositoryManager(Param)’:
x/setup.hpp:19:53: error: expected primary-expression before ‘>’ token
di::bind<events::Manager>().to<events::Manager>().in(di::singleton)
^
x/setup.hpp:19:55: error: expected primary-expression before ‘)’ token
di::bind<events::Manager>().to<events::Manager>().in(di::singleton)
^
x/setup.hpp:21:59: error: expected primary-expression before ‘>’ token
return injector.create<std::shared_ptr<RepositoryManager>>();
^~
x/setup.hpp:21:62: error: expected primary-expression before ‘)’ token
return injector.create<std::shared_ptr<RepositoryManager>>();
^
I have figured out I can change the definition like this and all is good:
template <typename Param>
inline std::shared_ptr<RepositoryManager> createRepositoryManager(Param p) {
(void)p;
auto injector = di::make_injector(
di::bind<events::Manager>().template to<events::Manager>().in(di::singleton)
);
return injector.template create<std::shared_ptr<RepositoryManager>>();
}
I'd like, however, to understand why. The events::Manager
and RepositoryManager
are normal classes (complete, not templates). I don't see how I could be in a dependent context here unless there's some funny rule I do not understand.
Oh, and just out of curiosity I've tried the code below and it also compiles. I'm lost.
template <typename Param>
inline std::shared_ptr<RepositoryManager> createRepositoryManager(Param p) {
(void)p;
auto injector = di::make_injector();
return injector.create<std::shared_ptr<RepositoryManager>>();
}
Edit:
It has been marked as duplicate of: Where and why do I have to put the "template" and "typename" keywords? Well, I've read that before asking and it still does not explain my situation (unless I'm really missing something). Neither template parameter type, nor parameter value is used here, so my understanding is I'm in an independent context and I should be able to call the templated methods just fine. So where am I wrong?