I'm trying to implement a "decoder" which can treat input data differently depending on the expected return type.
The following code seemed to work in https://cppinsights.io/:
#include <cstring>
#include <vector>
template<template <class, class> class V, typename T>
void Bar(V<T, std::allocator<T>> &v, char** c) {
size_t s = *(size_t*)*c;
v.resize(s);
memcpy((char*)&v[0], *c, s * sizeof(T));
}
template<typename T>
inline void Bar(T &t, char** c) {
t = *(T*)*c;
}
template<typename T>
T Foo(char** c) {
T t;
Bar<T>(t, c);
return t;
}
char bob[] = {8,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,9,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0};
char boz[] = {5,0,0,0};
int baz = Foo<int>((char **)&boz);
std::vector<int> bub = Foo<std::vector<int>>((char **)&bob);
So I thought that the final call to Foo
would use the first definition of Bar
but this is not happening, if I delete the second definition of Bar
, the following code does not compile:
#include <cstring>
#include <vector>
template<template <class, class> class V, typename T>
void Bar(V<T, std::allocator<T>> &v, char** c) {
size_t s = *(size_t*)*c;
v.resize(s);
memcpy((char*)&v[0], *c, s * sizeof(T));
}
template<typename T>
T Foo(char** c) {
T t;
Bar<T>(t, c);
return t;
}
char bob[] = {8,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,9,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0};
std::vector<int> bub = Foo<std::vector<int>>((char **)&bob);
and I get the following error message:
error: no matching function for call to 'Bar'
template<typename T> T Foo(char** c) { T t; Bar<T>(t, c); return t; }
^~~~~~
note: in instantiation of function template specialization 'Foo<std::vector<int>>' requested here
std::vector<int> bub = Foo<std::vector<int>>((char **)&bob);
^
note: candidate template ignored: invalid explicitly-specified argument for template parameter 'V'
template<template <class, class> class V, typename T> void Bar(V<T, std::allocator<T>> &v, char** c) {
^
I can't really understand what it means, why is the compiler not using the definition with the "template template" parameter? I have similar functions for "encoding" the data and it works, what am I doing wrong?
Am I trying to solve the wrong problem? How can I "split" the decoding function depending on the expected return type, while keeping it generic (or at least have a different handling of vector vs non-vector types)? Thanks.
CodePudding user response:
You are trying to pass T
, which is a concrete type, in Foo()
when you write Bar<T>(...)
. Instead, you'd need a template<class, class> class V
there, i.e., a class template with two type arguments.
CodePudding user response:
I believe the issue is inside Foo
. You're calling Bar<T>
which is explicitly saying use the Bar
that takes a single template argument. IE, you're making sure the template template
specialization never gets selected. Instead, let it auto-deduce.
This worked for me: https://godbolt.org/z/14h1fdTMT
template<typename T>
T Foo(char** c) {
T t;
Bar(t, c); // auto-deduce here
return t;
}