extracting container type from template argument

Hi, I'm wondering if there is a way to rewrite this code that's using 3 template parameters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<
	typename ELEM,
	typename ALLOC,
	template<typename, typename> class CONTAINER
>
class X {
	CONTAINER<ELEM, ALLOC> elements;
        ELEM random_element;
};

int main()
{
	X<int, std::allocator<int>, std::vector> x;
}


to something like this so I only kind of have to use 1 parameter

1
2
3
4
5
6
7
8
9
10
11
12
template<
	template<typename ELEM, typename ALLOC> class CONTAINER
>
class X {
	CONTAINER<ELEM, ALLOC> elements;
	ELEM random_element;
};

int main()
{
	X<std::vector<int, std::allocator<int>>> x;
}

The last code is of course not working and I cant figure out how to make it work without using something like this
1
2
3
4
5
6
7
8
9
10
11
12
13
template<typename CONTAINER>
using ELEM = typename CONTAINER::value_type;

template<typename CONTAINER>
class X {
	CONTAINER elements;
	ELEM<CONTAINER> random_element;
};

int main()
{
	X<std::vector<int, std::allocator<int>>> x;
}

I want to extract that value type and allocator type from tempalte arguments (like I tryed in code 2)without using value_type and allocator_type

I want to see if its possible with some changes to make 2nd code snippet work.
> without using value_type and allocator_type
> I want to see if its possible

It's possible, but why won't you use the container's value_type and allocator_type?

1
2
3
4
5
6
7
8
9
10
11
#include <type_traits>
#include <utility>

template< typename CONTAINER > struct X
{
    using container_type = CONTAINER ;
    using element_type = typename std::remove_reference< decltype( std::declval<container_type>().front() ) >::type ;
    using alloc_type = decltype( std::declval<container_type>().get_allocator() ) ;

    // ...
};

http://coliru.stacked-crooked.com/a/4d7aa3f600827ad7
Hey, tnx for answer man but I wanted to know can I get the right types without using using like in my 2nd code (which is not working)

1
2
3
4
template<
	template<typename ELEM, typename ALLOC> class CONTAINER
>
class X {...};


I hoped that ELEM would become passed containers element type and ALLOC respectively allocators type. This would be the most elegant solution. If I wanted to use containers value_type than I could just instantly do this

ELEM element_of_type_value_type = ... ;

If this kind of stuff possible to do?
Last edited on
> If this kind of stuff possible to do?

No; it violates the scoping rules.

3.3 Scope
    3.3.1 Declarative regions and scopes 
    Every name is introduced in some portion of program text called a declarative region, which is the largest part
    of the program in which that name is valid, that is, in which that name may be used as an unqualified name
    to refer to the same entity. 
...
        3.3.9 Template parameter scope
             3.3.9/1 The declarative region of the name of a template parameter of a template template-parameter 
                     is the smallest template-parameter-list in which the name was introduced.
...


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// begin declarative region (template declaration)
template <
                typename A,
                typename B,
                template <
                // begin declarative region (template template-parameter-list)
                                    typename C = A, // fine: within the template declaration where the name 'A' was introduced
                                    typename D = C // fine: within the declarative region where the name 'C' was introduced
                // end declarative region (template template-parameter-list)
                > class E,
                typename F = E<int,char> // fine: within the declarative region where the name 'E' was introduced
                // , typename G = C  *** error: outside the declarative region where the name 'C' was introduced
              >
    struct S
    {
        A a ; // fine: within the template declaration where the name 'A' was introduced
        E<A,A> e ; // fine: within the template declaration where the name 'E' was introduced

        // C c ; // *** error: outside the declarative region where the name 'C' was introduced
    };
// end declarative region (template declaration) 
Cool, yea if I think about it now this makes sense. Tnx a lot man for answer, this means that ::value_type is the way to go :)
Topic archived. No new replies allowed.