Что такое идиома template ‹typename T, T t›?

Я читал это и пытался понять, о чем был N3601. Он сказал, что эта идиома часто встречается при поиске в Интернете, но я ничего не нашел. Что

template<typename T, T t>

идиома, что это решает, как это используется, что такое неявные параметры шаблона и что предложение направлено на исправление?


person Jorge Ortega    schedule 13.04.2013    source источник
comment
Начните с шаблона template <typename T> void foo(T t);. Сделайте этот параметр значением времени компиляции: template <typename T, T t> void bar(); (я думаю, вы имели в виду это вместо class). Теперь подумайте, как вы можете вызвать foo(5);, чтобы T был int, но чтобы сделать это с bar, вам понадобится bar<int, 5>();. Это идет в правильном направлении?   -  person chris    schedule 13.04.2013
comment
Я имел в виду T t, а не класс T. Исправлено.   -  person Jorge Ortega    schedule 13.04.2013
comment
@chris Я вижу, куда ты сейчас идешь. bar должен быть общим для любого типа, который мы ему даем, но также принимает значение того же типа в качестве другого параметра шаблона. Нам нужно указать и тип, и значение, чтобы сделать вывод, что 5 - это int. В предложении показано использование этого в библиотеке отражений, но я никогда не видел этого до сегодняшнего дня. Как еще это можно использовать?   -  person Jorge Ortega    schedule 13.04.2013
comment
+1. Ах! Мне понравилось это предложение. Думаю, это может помочь мне решить эту проблему, которую нельзя решить с помощью C ++ 11.   -  person Nawaz    schedule 13.04.2013
comment
@Nawaz, Хорошее замечание. На самом деле я не думал о том, что он может позволить, чего не может C ++ 11 таким образом.   -  person chris    schedule 13.04.2013
comment
настолько круто, что так много людей заинтересовались новым C ++   -  person innochenti    schedule 13.04.2013


Ответы (2)


Решаемая проблема заключается в выводе типов из параметров шаблона, не являющихся типами.

Данный:

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

можно вывести T для foo (например, foo(10) приведет к выводу T как int), но невозможно вывести T для bar (bar<10>() просто не будет компилироваться, вы должны записать его как bar<int,10>()).

N3601 предлагает исправить это, представив синтаксис:

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

что позволит bar<10>() скомпилировать и вывести тип T.

person Mankarse    schedule 13.04.2013

Введение в статью вводит в заблуждение: идиома на самом деле

 template <typename T, T t>

Он обозначает шаблон, который зависит от типа T и значения t этого типа. Обозначения немного тяжелы, поскольку в большинстве случаев тип может быть выведен из самого значения.

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>();
}

Предложение состоит в том, чтобы ввести немного «синтаксического сахара», чтобы упростить запись нотации.

Кроме того, приведенный выше пример тривиален по своему описанию (и, возможно, неверен, поскольку параметры шаблона должны быть constexpr), но в документе описывается несколько ситуаций, когда текущая нотация может стать довольно сложной, что снижает удобочитаемость и общую простоту программирования.

person didierc    schedule 13.04.2013
comment
и значение t этого типа должно быть целочисленной константой или указателем, потому что в аргументах шаблона не допускается ничего другого. - person v.oddou; 04.06.2015