lundi 26 septembre 2022

Template resolution with template template parameter

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.

Aucun commentaire:

Enregistrer un commentaire