May std :: tuple_element double as a universal template argument repository?

This question made me think. Sometimes it is useful to extract the actual argument of the class template specialization, if it can not determine the public typedefargument. In C ++ 03, this is a sign of poor template design or the opposite design intent, and not particularly common. But variable templates make typedef coverage impossible, so it would be nice to have a tool to solve the problem without extra work.

C ++ 0x solves the problem typedeffor a particular variations template tuple.

tuple_element< 2, tuple< char, short, int > >::type my_int; // nth element type

But tuple_elementnot married to tuple; he also works with pairand array. His statement is not mentioned tuple.

template< size_t index, typename something_like_a_tuple >
struct tuple_element; // general case is left incomplete, unimplemented

tuple related by partial specialization:

template< size_t index, typename ... tuple_elements >
struct tuple_element< index, tuple< tuple_elements ... > > { // impl. in here

But this is optional. The template template parameter can match tuple, according to any other template, parameterized only over types.

template< size_t index,
    template< typename ... > class template_over_types,
    typename ... types >
struct tuple_element< index, template_over_types< types ... > > {

It will allow

tuple_element< 1, almost_any_template< char, int > >::type my_int;
tuple_element< 0, pair< int, char > >::type another_int; // same specialization

and yet allow additional specialization for array

template< size_t index, typename element, size_t extent >
struct tuple_element< index, array< element, extent > > 
    { typedef element type; }

Conflict is not possible because the arraysecond argument size_t, not the type.


Unfortunately, the user is allowed to specialize the interface tuple_elementfor their types. The user's precondition and their guarantee are provided by C ++ 0x §17.6.3.2.1 / 1:

The program can add the template specialization for any standard library template to the std namespace only if the declaration depends on the user type, and the specialization meets the requirements of the standard library for the original template and is not explicitly prohibited.

, array, - , . , , getter .

(.. ), , , , , . A B. , A B, B , B . . B . , , , .

, , .

, B ​​. , , , , .

, - , .

, ​​ . tuple_element , user_type.

 template< size_t I,
           template< typename ... > class any_template,
           typename ... T, typename ... U >
 struct tuple_element< I, any_template< T ..., ::user_type, U ... > >;

..., user_type, ... , , , user_type.

- , .

( tuple, as-if. , , , .)


. ? std::tuple_element?

+3
1

, , - , . , , getter .

. ?


std:: tuple_element?

.

template<int A, char B, long C, class D, int &X, int(*Handler)()>
struct funny_template { };

int x, y();
std::tuple_element<3, funny_template<1, 2, 3, long, x, y> >::type along = 0;

:)


. ?

template<class A1, ..., class AN>
class T<Am1, ..., AmM>;

template<class B1, ..., class BL>
class T<Bm1, ..., BmM>;

template<class A1, ..., class AN>
void f(T1<Am1, ..., AmM>);

template<class B1, ..., class BL>
void f(T2<Bm1, ..., BmM>);

, , , , ,

T1A<Uam1, ..., UAmM> -> T2<Bm1, ..., BmM>
T2A<UBm1, ..., UBmM> -> T1<Am1, ..., AmM>

, , . BmM typename Foo::X, , . , , Foo::X AmM , AmM .

, (... , ), , , . .

+1

Source: https://habr.com/ru/post/1764459/


All Articles