Can a function return an arbitrary container?

Let's say I have a "construct" function.

The construct function takes an argument that specifies which container the user wants to be constructed.

For example, construct("vector", ...) will cause construct to make and return a vector.

Whereas construct("list", ...) will cause construct to make and return a linked list.

I can't really find a notation to make this work, however. Does it need to be a template? And how would it look? Nothing I try is working...
Last edited on
You can overload a function, if that's what you were looking for.

1
2
void function(int x);
void function(float x)


Similar to that, then the appropriate version will run based on what you passed it.

EDIT: Oh wait, never mind I just got what you were asking, sorry. You would have to make multiple functions for different return types.
Last edited on
I don't want to overload the function because the code is exactly the same for every container.

I just want a "Container" type instead of having to specify "Vector" or "Deque".
(codes not tested)
If you use a function template the compiler will create a new construct function for each type.
e.g. if your template is
1
2
3
4
5
template<typename T, typename U> T construct(U var){
    T newT;
    //do stuff
    return newT;
}

and you use it like
1
2
std::vector<int> vect = construct<std::vector<int>, int>(5);
std::list<float> lis = construct<std::list<float>, float>(0.3f);

the compiler would create
1
2
3
4
5
6
7
8
9
10
std::vector<int> construct(int var){
    std::vector<int> newT;
    //do stuff
    return newT;
}
std::list<float> construct(float var){
    std::list<float> newT;
    //do stuff
    return newT;
}

helpful link:
http://en.cppreference.com/w/cpp/language/function_template

You can also pass pointers to the function and have the function populate the data pointed to by the pointer. This requires creating the vector/list before passing the pointer to it to the function.
http://www.cplusplus.com/doc/tutorial/pointers/
1
2
3
4
5
6
7
8
void construct(vector pointer = 0, list pointer = 0, ...){
    if(vector pointer != 0){
        //do stuff with vector pointer
    }
    if(list pointer != 0){
        //do stuff with list pointer
    }
}


There is one other way I can think of, but it is considered to be bad. In this method the function returns a void pointer. The void pointer points to the location of the required type. After calling this function, the pointer needs to be cast back to its original type before it can be used.
1
2
3
4
5
6
7
8
9
10
11
12
13
void*construct(std::string type, ...){
    std::vector<int> *vect = new std::vector<int>;
    std::list<float> *lis = new std::list<float>;
    //do stuff
    if(type == "vector"){
        delete lis;
        return typecasted vect to void*
    }
    if(type == "list"){
        delete vect;
        return typecasted lis to void*
    }
}

Make sure you clean up after you have finished with the pointer.
Last edited on
Thanks for the tips! I was able to make it work.

One last quick question.

If I have a template like this:

construct<vector<int>>(...)

And my functions looks like this:

1
2
3
4
5
6
template <typename Object>
Object construct(...)
{
       ....
       foo<T>(...) // T refers to the type of the elements of the object, in this case 'int'.
}


Is there any possible way for me to deduce the type of T by just examining the Object?

That is to say, I do NOT want to make construct take two template arguments like this:

construct<vector<int>, int>(...)

/\ To me, that is verbose and redundant. I only want construct to take 'vector<int>' as its template argument, since that does, indeed, contain all the information the function needs in order to run.

Any advice?


I'm not really sure what you're asking, but would these help?
http://www.cplusplus.com/forum/general/21246/
http://www.cplusplus.com/reference/typeinfo/
>I s there any possible way for me to deduce the type of T by just examining the Object?

Yes; typename Object::value_type

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <vector>

template < typename SEQ_CONTAINER > SEQ_CONTAINER construct_from_stdin()
{
    SEQ_CONTAINER result ;

    typename SEQ_CONTAINER::value_type value ; // the type of values held by the container

    while( std::cin >> value ) result.push_back(value) ;

    return result ;
}

int main()
{
    const auto seq = construct_from_stdin< std::vector<int> >() ;

    for( int v : seq ) std::cout << v << ' ' ;
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/dc8368ae30a0df98
Topic archived. No new replies allowed.