Компилятор выводит аргумент шаблона - PullRequest
1 голос
/ 15 февраля 2020
template<typename T>
class A
{
    public:

    A(T &t)
    : t_(t){}

    T t_;
};


int main()
{
    int value;
    A<decltype(value)> a(value);
    // what I wish for : A a(value); 
    // which does not compile "missing template argument before 'a'"
}

Есть ли способ в объявлении A (или где-то еще) подсказать компилятору, что T должен автоматически разрешаться в тип, передаваемый конструктору?

(в идеале c ++ 11 , но рад слышать о менее старых версиях)

Ответы [ 3 ]

6 голосов
/ 15 февраля 2020

C ++ 17 делает это из коробки (или с помощью руководств по выводам), предыдущие версии не могут.

4 голосов
/ 15 февраля 2020

Как ответил @Quentin, это возможно только начиная с C ++ 17. Однако, если вы в порядке с вызовом функции для создания ваших A объектов, следующее должно делать то, что вы хотите в C ++ 11:

template <class T, class NonRefT = typename std::remove_reference<T>::type>
A<NonRefT> create_A (T && t) {
  return A<NonRefT>(std::forward<T>(t));
}

// Or even closer to your original code:
template <class T>
auto create_A (T && t) -> A<decltype(t)> {
  return A<decltype(t)>(std::forward<T>(t));
}

Я использовал std::remove_reference на основе вашего использования decltype, хотя вы можете вместо этого использовать std::decay.

int main () {
  int value = 5;
  auto a = create_A(value);
}

Если я правильно помню, пример кода имеет крайний случай, где он не работает как ожидалось до C ++ 17. Компилятор исключит конструктор копирования / перемещения для создания a из значения r, возвращаемого create_A(). Однако во время компиляции он будет проверять, доступен ли / 101 * конструктор копирования / перемещения (который он не будет использовать). Начиная с C ++ 17, удаление / перемещение выполняется «правильно», и для такого кода не требуется конструктор копирования / перемещения. (Кроме того, я могу ошибаться, и вместо этого он может проверять назначение копирования / перемещения.)

2 голосов
/ 15 февраля 2020

В C ++ 11 вы можете создать простую make_A функцию, подобную этой:

#include <iostream>

template <typename T>
class A {
public:
    A(T &t) : t_(t) {}

    T t_;
};

template <typename T>
A<T> make_A(T&& t) {
    return A<T>(std::forward<T>(t));
}

int main() {
    int value = 0;
    auto a = make_A(value);

    return 0;
}

Демо

...