Когда компилятор может определить параметр шаблона?

Иногда работает иногда нет:

template <class T> 
void f(T t) {}

template <class T>
class MyClass {
public:
  MyClass(T t) {}
};

void test () {
  f<int>(5);
  MyClass<int> mc(5);
  f(5);
  MyClass mc(5); // this doesn't work
}

Есть ли способ обойти приведенный выше пример? Т.е. заставить компилятор вывести параметр шаблона из параметра конструктора.

Будет ли это исправлено в будущем или есть веская причина не делать этого?

Каково общее правило, когда компилятор может вывести параметр шаблона?


person Łukasz Lew    schedule 28.04.2009    source источник


Ответы (3)


Параметры шаблона можно вывести для шаблонов функций, если тип параметра можно вывести из параметров шаблона.

Итак, здесь можно сделать вывод:

template <typename T>
void f(T t);

template <typename T>
void f(std::vector<T> v);

но не здесь:

template <typename T>
T f() {
  return T();
}

И не в шаблонах классов.

Итак, обычное решение вашей проблемы - создать функцию-оболочку, аналогичную стандартной библиотечной функции std::make_pair:

  template <class T>
    class MyClass {
    public:
        MyClass(T t) {}
        void print(){
            std::cout<<"try MyClass"<<std::endl;
        }
    };

    template <typename T>
    MyClass<T> MakeMyClass(T t) { return MyClass<T>(t); }

а затем вызовите auto a = MakeMyClass(5);, чтобы создать экземпляр класса.

person jalf    schedule 28.04.2009
comment
+1, основательно. Незначительный недостаток: я предлагаю изменить, когда тип параметра зависит от того, когда зависит тип параметра. - person j_random_hacker; 28.04.2009
comment
void f (typename T :: const_iterator t); ‹< здесь, T появляется в невыводимом контексте. даже при вызове его с вектором ‹int› :: const_iterator, например, он не сможет вывести вектор ‹int› для T. Причина в том, что значение :: const_iterator зависит от T., но T снова зависит о значении :: const_iterator. вот почему boost :: implicit_cast кодируется так: template ‹typename T› T implicit_cast (typename identity ‹T› :: type t) {return t; } и здесь мы снова имеем невыводимый контекст. - person Johannes Schaub - litb; 28.04.2009
comment
Standard-ref - 14.8.2.4/4 (в последнем проекте c ++ 1x он расположен по адресу 14.9.2.5/5 - также исправлены некоторые недостатки формулировки в текущем стандарте). :) ваше здоровье - person Johannes Schaub - litb; 28.04.2009
comment
Да ты, конечно, прав. Не знаю, о чем я думал. - person jalf; 28.04.2009
comment
Этот ответ требует обновления, поскольку C ++ 17 представил некоторые новые функции для вывода аргументов шаблона . - person Anderson Green; 23.06.2019

Прочтите Выведение аргументов шаблонаADL или поиск по Кенигу).

person dirkgently    schedule 28.04.2009
comment
Это ответ только по ссылке, подумайте о том, чтобы улучшить этот ответ, предоставив соответствующую информацию из упомянутого материала. - person Krupip; 16.05.2019

В C ++ 17 можно вывести некоторые типы с помощью auto, хотя здесь все же необходимо указать параметры шаблона:

#include <iostream> 
#include <string>

template <class T1,class T2>   
auto print_stuff(T1 x, T2 y) 
{ 
    std::cout << x << std::endl;
    std::cout << y << std::endl;
}

int main() 
{ 
    print_stuff(3,"Hello!");
    print_stuff("Hello!",4);
    return 0; 
}

Используя флаг -fconcepts в gcc, можно вывести параметры, хотя это еще не часть C ++ стандарт:

#include <iostream> 
#include <string>

auto print_stuff(auto x, auto y) 
{ 
    std::cout << x << std::endl;
    std::cout << y << std::endl;
}

int main() 
{ 
    print_stuff(3,"Hello!");
    print_stuff("Hello!",4);
    return 0; 
}
person Anderson Green    schedule 25.06.2019