Компилятор, определяющий аргумент шаблона

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 ответа

Решение

В 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;
}

Демо

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

Как ответил @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 из rvalue, возвращенного create_A(). Однако во время компиляции он проверяет,AКонструктор копирования / перемещения (который он не будет использовать) доступен / доступен. Начиная с C++17 исключение копирования / перемещения выполняется "правильно", и для такого кода не требуется конструктор копирования / перемещения. (Кроме того, я могу неправильно вспомнить, и вместо этого может проверять назначение копирования / перемещения.)

Другие вопросы по тегам