Specifying template parameter by name?

Hi,
So I have a class template that has quite alot of template parameters, and all of them have default types.
The problem im facing is that it becomes quite tedious when i want to specify a different type of *one* of those template parameters (especially when its one of the very last ones),
because i then have to re-specify the types of every single template parameter all the way up to the only one i actually wanted to change.

So i'm just wondering: is it possible to express which template parameter you want to specify a type for, without having to re-specify all the parameters that come before it?

Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
template <typename T=int, typename U=float> 
struct example
{
  T t;
  U u;
};

int main()
{
  example<U=double> ex; //i dont want to have to re-specify that T is int in order to specify U
  return 0;
}
Last edited on
Unfortunately, you can only do that with the leftmost template argument, given that all the other arguments have default values. That is just how the language is implemented. This gets even more annoying when using standard library containers and trying to change the template parameters that are farther in the list. You would have to manually enter the ones before it.
Last edited on
This is a little old school, but the point is illustrating a potential approach

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
template <typename Di>
struct iidx_type
{
 typedef int A;
 typedef int B;
 typedef double C;
 typedef Di D;
};

template <typename Bi>
struct ixfd_type
{
 typedef int A;
 typedef Bi B;
 typedef float C;
 typedef double D;
};

template <typename P>
struct example
{
 typedef typename P::A A;
 typedef typename P::B B;
 typedef typename P::C C;
 typedef typename P::D D;
};




int main()
{
 example< iidx_type< int >> a;
 example< ixfd_type< float >> b;
 
 return 0;
}


The idea is, for example, that iidx indicates "integer, integer, double, parameter", where "D" is the parameter

or ixfd indicates "integer, parameter, float, double", where "B" is the parameter
Last edited on
If you find yourself with gazillions of template arguments, something is wrong with your design.

Try to minimize the number of templates, and organize it such that argument types depend on prior argument types.

This is the way, for example, the Standard Library does it. Take the std::string class:

1
2
3
4
5
template< 
    class CharT, 
    class Traits = std::char_traits<CharT>, 
    class Allocator = std::allocator<CharT>
> class basic_string;

For most use cases, you only need to specify the CharT type and the following types sort themselves.

For more unusual needs, a simple using or typedef will make life easy.

Hope this helps.
> i want to specify a different type of *one* of those template parameters
> without having to re-specify all the parameters that come before it

Something like this, perhaps; (worth it only if specifying just one arbitrary template argument is something that you want to do over and over again):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <type_traits>
#include <iosfwd>

template < typename FIRST = int, typename SECOND = double,
           typename THIRD = void, typename FOURTH = char >
struct example { /* ... */ };

enum param { FIRST, SECOND, THIRD, FOURTH };

namespace detail
{
    template < param, typename > struct example_maker ;

    template < typename TYPE > struct example_maker<FIRST,TYPE>
    { using type = example<TYPE> ; } ;

    template < typename TYPE > struct example_maker<SECOND,TYPE>
    { using type = example<int,TYPE> ; } ;

    template < typename TYPE > struct example_maker<THIRD,TYPE>
    { using type = example<int,double,TYPE> ; } ;

    template < typename TYPE > struct example_maker<FOURTH,TYPE>
    { using type = example<int,double,void,TYPE> ; } ;
}

template < param PARAM, typename TYPE >
using example_t = typename detail::example_maker<PARAM,TYPE>::type ;

int main()
{
    example_t< FIRST, long > ex1 ; // example< FIRST = long >
    static_assert( std::is_same< decltype(ex1), example<long> >::value ) ;

    example_t< SECOND, short > ex2 ; // example< SECOND = short >
    static_assert( std::is_same< decltype(ex2), example<int,short> >::value ) ;

    example_t< THIRD, char > ex3 ; // example< THIRD = char >
    static_assert( std::is_same< decltype(ex3), example<int,double,char> >::value ) ;

    example_t< FOURTH, std::ostream& > ex4 ; // example< FOURTH = std::ostream& >
    static_assert( std::is_same< decltype(ex4), example<int,double,void,std::ostream&> >::value ) ;
}

http://coliru.stacked-crooked.com/a/2a1fe7a0c5faa252
https://rextester.com/ZRPXE55003
Last edited on
Topic archived. No new replies allowed.