I have the following wrapper-maker metametafunction:
template <class ToWrap>
struct wrapper_maker
{
template <bool>
struct wrapper
{
wrapper(ToWrap& a) : a(a) { }
ToWrap& a;
};
};
I want to use it in this template function foo
:
template <class ToWrap>
void foo(typename wrapper_maker<ToWrap>::template wrapper<true>& wrapped)
{
cout << "foo" << endl;
}
Note: the use case is that foo
already exists with different overloads, yet I want this particular overload to be called if the object is a wrapper_maker<ToWrap>::wrapper<bool>
instance.
However, when I write a function that calls foo
with such an object:
template <class ToWrap>
void call_foo(ToWrap& o)
{
typedef typename wrapper_maker<ToWrap>::template wrapper<true> wrapped_t;
wrapped_t wrapped(o);
foo(wrapped);
}
Using it as so:
int to_wrap = 5;
call_foo(to_wrap);
I get this error:
prog.cpp: In instantiation of 'void call_foo(ToWrap&) [with ToWrap = int]':
prog.cpp:32:18: required from here
prog.cpp:27:16: error: no matching function for call to 'foo(wrapped_t&)'
foo(wrapped);
^
prog.cpp:27:16: note: candidate is:
prog.cpp:17:6: note: template<class ToWrap> void foo(typename wrapper_maker<ToWrap>::wrapper<true>&)
void foo(typename wrapper_maker<ToWrap>::template wrapper<true>& wrapped)
^
prog.cpp:17:6: note: template argument deduction/substitution failed:
prog.cpp:27:16: note: couldn't deduce template parameter 'ToWrap'
foo(wrapped);
Why is that?
EDIT: Further, is there any way to define a specialization of foo
that will get called on instances of wrapper_maker<T>::wrapper<W>
, for any possible T
, without having to specify either T
or W
at the call-site?
This:
Is a non-deduced context. Specifically, the first one in the list from [temp.deduct.type]4/5:
You need to explicitly pass in
ToWrap
to make that work.Let me provide another example as to why this may be the case. Suppose we had:
In general, in order to implement this, the compiler would have to know every possible specialization of
some_fn
- even if there were only one for whichsome_fn<T>::type
wereint
.In general, no, for the same reasons articulated above. However, you can just add additional info to
wrapper
: