Jacob Ritchie
Jacob Ritchie

Reputation: 1401

C++ Templates: override some, but not all, default arguments?

When I come across a template with several default arguments, e.g.

template<typename ID = int, typename PAYLOAD = std::string>
class Foo{};

Is there a way for me to override just a few of the default arguments, instead of all of them?

I.e. instead of writing the following to create a class that uses an integer instead of a std::string for the PAYLOAD parameter,

typedef Foo<int,int> Bar;

Can I write something similar to:

typedef Foo<PAYLOAD=int> Bar;

I am dealing with another team's pre-defined templates with a lot of default arguments, and being able to use the second method seems like it would improve the clarity of my code.

Looking at the documentation and other questions on StackOverflow, it does not seem to be possible, but I was wondering if someone could explain why this isn't a feature?

Upvotes: 3

Views: 1963

Answers (3)

Niall
Niall

Reputation: 30606

No.

Template types are not supported like that. Types can be specified in place of the defaults in left to right order.

Upvotes: 2

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275230

You can replace by index, if the template fakes nothing but types.

Create the template with the first n args bound. Then extract the arguments and replace the ones you want.

This requires the first n arguments be valid without the positional ones.

Sketch:

 template<class...>struct types{using type=types;};
 template<class types, class T, size_t index>
 struct replace{
   using type=/*types with index replaced with `T`*/;
 };
 template<template<class...>class Z,class types>
 struct apply;// applies content of types to Z
 template<size_t n, class T>struct rep{};
 template<class Z, class...reps>
 struct replacing;
 template<template<class...>class Z, class...Ts,class...reps>
 struct replacing<Z<Ts...>,reps...>:
   apply<Z,replacing_t<types<Ts...>,reps...>>
 {};
 template<class...Ts,class T0,class n,class...reps>
 struct replacing<types<Ts...>,rep<n,T0>,reps...>:
   replacing<replace_t<types<Ts...>,T0,n>,reps...>
 {};
 template<class...Ts>
 struct replacing<types<Ts...>>:
   types<Ts...>
 {};

with _t using aliases and a number of ops left blank.

Then you can:

 replacing_t<some_template<>,rep<1,int>>

which uses the default args of some_template, but replaces arg1 with int.

Upvotes: 0

Maksim Solovjov
Maksim Solovjov

Reputation: 3157

In the Design and Evolution of C++, Bjarne Stroustrup mentioned that there were proposals for keyword arguments; however, they were rejected, since

the extensions group reached a consensus that the proposal was close to redundant, would cause compatibility problems with existing C++ code, and would encourage programming styles that ought not to be encouraged.

I suppose keyword template parameters were not included for the same reason. If you want to simplify your life, either typedef the complexity away, or write adapter classes that reorder the template parameters.

Upvotes: 4

Related Questions