I've written a number of templated functions. Example:
template <typename T>
inline int Foo(T* t, unsigned char** p, size_t* size, size_t (*MyHandler)(T*))
{
...
}
template <>
inline int Foo<Bar>(Bar* t, unsigned char** p, size_t* size, size_t (*MyHandler)(Bar*))
{
...
}
If I call these functions with explicit template arguments then all works well, i.E.
Foo<Bar>(&myBar, pBuffer, size, FooFoo<Bar>);
FooFoo<T> be a different templated function
It would be highly advantageous if a user would not need to keep track of types. So I'd like to use the following syntax:
Foo(&myBar, pBuffer, size, FooFoo);
However, this line is causing a pair of
As with Foo, there exists a specialization FooFoo<Bar>
To my knowledge, it should be possible to have T deduced, because of the first argument, which is of type T* - Or is that function pointer messing with the deduction?
Any hints would be greatly appreciated.
Update 3 A MCVS as per the request with changes suggested by @Yakk which finally works!
#include <stdio.h>
struct Bar
{
int a;
int b;
int c;
};
template<class T>struct id_t{typedef T type;};
template <typename T>
inline size_t FooFoo(T* t)
{
printf("FooFoo calculating size of T...\r\n", sizeof(T));
return sizeof(T);
}
template <>
inline size_t FooFoo<Bar>(Bar* t)
{
printf("FooFoo calculating size of Bar...\r\n", sizeof(Bar));
return sizeof(Bar);
}
template <typename T>
inline int Foo(T* t, unsigned char** p, size_t* size, typename id_t<size_t (*)(T*)>::type MyHandler)
{
printf("Foo telling size of T: %u\r\n", MyHandler(t));
return 0;
}
template <>
inline int Foo<Bar>(Bar* t, unsigned char** p, size_t* size, typename id_t<size_t (*)(Bar*)>::type MyHandler)
{
printf("Foo telling size of Bar: %u\r\n", MyHandler(t));
return 0;
}
int main(int argc, char* argv[])
{
int i;
Bar myBar;
Foo<Bar>(&myBar, nullptr, 0, FooFoo<Bar>); // works
Foo<int>(&i, nullptr, 0, FooFoo<int>); // works
Foo(&myBar, nullptr, 0, FooFoo<Bar>); // works
Foo(&i, nullptr, 0, FooFoo<int>); // works
Foo(&myBar, nullptr, 0, FooFoo); // error C2896: 'int Foo(T *,unsigned char **,size_t *,size_t (__cdecl *)(T *))' : cannot use function template 'size_t FooFoo(T *)' as a function argument
// error C2784: 'int Foo(T *,unsigned char **,size_t *,size_t (__cdecl *)(T *))' : could not deduce template argument for 'T *' from 'Bar *'
Foo(&i, nullptr, 0, FooFoo); // error C2896: 'int Foo(T *,unsigned char **,size_t *,size_t (__cdecl *)(T *))' : cannot use function template 'size_t FooFoo(T *)' as a function argument
//error C2784: 'int Foo(T *,unsigned char **,size_t *,size_t (__cdecl *)(T *))' : could not deduce template argument for 'T *' from 'int *'
return 0;
}
Many thanks!
All arguments have equal weight when deducing, and are deduced independently. To block using a particular argument for deduction, do this:
template<class T>struct id_t{typedef T type;};
template<class T>using block_deduction=typename id_t<T>::type;
Now take size_t (*MyHandler)(T*) and make it:
block_deduction<size_t (*)(T*)> MyHandler
Or in a non-C++11 compiler:
typename id_t<size_t (*)(T*)>::type MyHandler
What this does is put the MyHandler argument's type into a non-deduced context. As such, the compiler does not try, and instead uses the deduction of the first argument to determine T. This then generates the type of MyHandler. The overload set you pass is then resolved based on the signature, and everything works (probably).
Your problem is not the deduction of T=Bar for Foo - it's the deduction for FooFoo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With