23

I was reading this and was trying to understand what N3601 was about. It said this idiom comes up a lot in a web search, but I couldn't find anything. What is the

template<typename T, T t>

idiom, what does it solve, how is it used, what is are Implicit template parameters, and what does the proposal aim to fix?

Jorge Ortega
  • 291
  • 1
  • 4
  • 11
  • 2
    Start with a template `template void foo(T t);`. Make that parameter a compile-time value: `template void bar();` (I think you meant that instead of `class`). Now think about how you can call `foo(5);` for T to be an `int`, but to do that with `bar`, you need `bar();`. Is that going in the right direction? – chris Apr 13 '13 at 03:20
  • I did mean T t, not class T. Fixed that. – Jorge Ortega Apr 13 '13 at 03:26
  • @chris I see what where you are going now. bar needs to be generic on any type we give it, but is also taking a value of that same type as another template parameter. We need to specify both the type and the value for it to deduced that 5 is an int. The proposal shows a usage of this in a reflection library, but I've never seen it until today. How else can this be used? – Jorge Ortega Apr 13 '13 at 03:36
  • +1. Ah! I loved this proposal. I think it *might* help me solve [this problem](http://stackoverflow.com/questions/14092058/pretty-print-types-and-class-template-along-with-all-its-template-arguments) which cannot be solved with C++11. – Nawaz Apr 13 '13 at 04:21
  • 1
    @Nawaz, Good point. I haven't actually thought about what it could allow that C++11 can't in that manner. – chris Apr 13 '13 at 04:44
  • so cool that so many people are intersted in new C++ – innochenti Apr 13 '13 at 10:56

2 Answers2

15

The problem that is being solved is deducing types from template non-type parameters.

Given:

template<typename T> void foo(T);
template<typename T, T> void bar();

it is possible to deduce T for foo (for example, foo(10) will result in T being deduced to be int), but it is not possible to deduce T for bar (bar<10>() will simply not compile, you have to write it as bar<int,10>()).

N3601 proposes fixing this by introducing the syntax:

template<using typename T, T> void bar();

which will allow bar<10>() to compile and cause the type T to be deduced.

Mankarse
  • 39,818
  • 11
  • 97
  • 141
5

The paper introduction is misleading: the idiom is actually

 template <typename T, T t>

It denotes a template which depends on a type T and a value t of that type. The notation is a bit heavy since in most situations the type could be deduced from the value itself.

E.g.

// the current definition notation
template <typename T, T t> void f() { t.f(); };

//// the proposed definition notation
//// the parameter t depends on an implicit typename parameter T
// template <using typename T, T t> void f() { t.f(); };

struct foo {
    void f(){ 
        // some computation
    }
};

foo bar;

int main(){
    // the current instantiation notation
    f<foo,bar>(); 
    //// the proposed instantiation notation 
    //// we know that bar is of type foo, so we don't need to specify it
    // f<bar>();
}

The proposal is about introducing a bit of "syntactic sugar" to make the notation easier to write.

Also, the example given above is trivial in its description (and possibly wrong, since template parameters need to be constexpr), but the paper describes several situations where the current notation can become quite hairy, reducing readability and overall ease of programming.

didierc
  • 14,572
  • 3
  • 32
  • 52
  • and the value `t` of that type has to be an integral constant, or a pointer because nothing else is allowed in template arguments. – v.oddou Jun 04 '15 at 02:55