Home > Back-end >  How do i use deduction to choose the return type of function
How do i use deduction to choose the return type of function

Time:04-09

I have a question regarding the full deduction with functions using C 11 standard. Basically I am ought to make a function that takes a single parameter that should look like a matrix (basically any container) whose elements can again be any container but having in mind that elements of every row do not necessarily need to be the same size. For an example the parameter could be vector of deques, classic C-like matrix, vector of vectors, deques of vectors and so on, you get the point. Having said that. Function itself needs to dynamically alocate (using fragmented and not continual allocation) memory for 2d matrix with same structure and type of elements and then copy all the elements from given matrix into it, and finally return a double pointer which you can use to access the elements of matrix. Having that said, I do not actually know how to use full deduction so that the function actually knows which type is the double pointer that it must return. First thing that crosses my mind is to use something like this:

template <typename MatrixType>
auto CreateMatrix (MatrixType M) -> decltype ... 

Logic behind it is that full deduction would find out what type of double pointer must be returned, but the three dots (...) is where im halted, i dont actually know what to write there.

Ofcourse I could probably do something like this:

template <typename MatrixType>
MatrixType** CreateMatrix (MatrixType M) 

But it doesn't use deduction because call like this:

std::vector<std::deque<double>> a = {...};
auto x = CreateMatrix(a);

wouldn't work without using <double> with the call of the function, so it is not a full "problem solved" it is just a cheap trick.

Memory allocation shouldn't be hard, I think It would be pretty easy to do, but currently I'm stuck here and do not know what to do.

I am grateful for every help!

CodePudding user response:

I am still not sure if I understood what you want to do. I will concentrate on the actual question: How to infer the value type from a 2D container when the container can be made of standard containers or C arrays?

You can use a type trait. Standard containers have a value_type member alias. When an 2d array is passed as pointer T** then the value type is T. When an array T[M][N] is passed by reference then the value type is T:

template <typename T>
struct value_type { using type = typename T::value_type; };

template <typename T>
struct value_type< T*> { using type = T; };

template <typename T,size_t N>
struct value_type< T[N] > { using type = T;};

template <typename T>
struct value_type2d {
    using type = typename value_type<typename value_type<T>::type>::type;
};

As an example I used a function that simple returns the first element:

template <typename Matrix>
typename value_type2d<Matrix>::type foo(const Matrix& m) {
    return m[0][0];
}



int main() {
    std::vector<std::vector<double>> x{{42,1},{2,3}};
    std::cout << foo(x) << "\n";
    std::vector<std::deque<double>> y{{42,1},{2,3}};
    std::cout << foo(x) << "\n";
    int z[2][2] = {{42,1},{2,3}};
    std::cout << foo(z) << "\n";
    std::vector<std::string> w[2] = {{"42","1"},{"2","3"}};
    std::cout << foo(x) << "\n";
}

Live Demo

PS: Yes decltype( M[0][0] ) is a simpler way to get the value type. Though for example std::map::operator[] is not const and you should not pass a non const referene when the function does not modify the parameter. And you certainly do not want to copy the whole matrix just to pass it to the function.

  • Related