Как заставить компилятор вывести аргумент шаблона класса?

Я новичок в шаблонах С++, и я (довольно безуспешно) пытаюсь заставить компилятор вывести аргумент имени типа шаблона при инициализации.

Вот мой код.

template <typename T>
class C
{
public:
        T a;
        C(T a) : a(a) {}
        C(const C<T>& other) : a(other.a) {}
};

int main()
{
        C<int> x(1);
        C y{ x };

        return 0;
}

Этот код, скомпилированный g++, приводит к ошибке.

test.cpp:13:11: error: missing template arguments before ‘y’
         C y{ x };
           ^

Я хотел бы сохранить этот синтаксис - просто C без явного указания аргумента шаблона.

Я пытался использовать руководства по дедукции, но это только вызвало еще одну ошибку.

template <typename T> C(const C<T>& other) -> C<T>;

Когда я вставил эту строку ниже определения класса C, я получил это.

test.cpp:10:51: error: expected constructor, destructor, or type conversion before ‘;’ token
 template <typename T> C(const C<T>& other) -> C<T>;
                                                   ^

Другая ошибка произошла, когда я поместил эту строку в определение класса C (вверху).

C(const C<T>& other) -> C<T>;
test.cpp:4:26: error: ‘C’ function with trailing return type not declared with ‘auto’ type specifier
  C(const C<T>& other) -> C<T>;
                          ^~~~

В обоих случаях ошибка первого упоминания все еще присутствует.

Благодарю вас!


person Tomáš Hons    schedule 21.04.2019    source источник
comment
Невозможно воспроизвести: я компилирую ваш исходный код без ошибок с помощью g++ (8.3.0) и clang++ (7.0.1). Вы уверены, что включили компиляцию C++17? Читая сообщения об ошибках, я подозреваю, что вы компилируете С++ 14 или С++ 11, а руководства по выводу представлены в С++ 17.   -  person max66    schedule 22.04.2019
comment
Спасибо. Моя ошибка - я использовал g++ 8.2.0, и по умолчанию это C++ 14. Он работает с С++ 17.   -  person Tomáš Hons    schedule 22.04.2019


Ответы (1)


В C++11 только функции шаблона могли выводить свои параметры шаблона. Например, учитывая:

void f(std::pair<int, char> &s);

, можно было бы назвать это с помощью

f(std::make_pair(5, 'c'));

, так как std::make_pair — это функция, и аргументы шаблона могут быть выведены для функций.

Тем не менее, это незаконно называть с парой:

f(std::pair(5, 'c'));

, так как для шаблонов классов нет вывода аргументов шаблона. Эта проблема была исправлена ​​в C++17, что сделало std::make_pair немного устаревшим.

Подробнее о новом выводе аргументов шаблона класса можно узнать здесь.

Чтобы решить вашу проблему, я смог получить ту же ошибку при компиляции с помощью gcc с использованием С++ 11. Код компилируется без ошибок на C++17 (для gcc это можно сделать, передав аргумент -std=c++17).

person Paul92    schedule 21.04.2019
comment
Спасибо. Моя ошибка - я использовал g++ 8.2.0, и по умолчанию это C++ 14. Он работает с С++ 17. - person Tomáš Hons; 22.04.2019