Вывод аргумента шаблона класса не работает с шаблоном псевдонима

Рассмотрите код, вставленный ниже. Я определил очень простой класс, для которого компилятор генерирует неявное руководство по выводу, чтобы его можно было создать без явных аргументов шаблона. Однако вычет аргумента шаблона не работает для создания объекта из простого шаблона псевдонима, который только перенаправляет непосредственно в целевой класс:

template< typename A, typename B >
struct Foo {
    Foo( A const &a, B const &b )
            : a_(a), b_(b)
    { }

    A a_;
    B b_;
};

template< typename A, typename B >
using Bar = Foo<A, B>;

auto foobar() {
    Foo r{1, 2};
    Bar s{3, 4};
    // ../src/geo/vector_test_unit.cpp: In function 'auto foobar()':
    // ../src/geo/vector_test_unit.cpp:16:6: error: missing template arguments before 's'
    //   Bar s{3, 4};
    //       ^
    return 1;
}

Как видно из приведенного выше комментария к коду, g++ выдает ошибку при использовании псевдонима шаблона без аргументов шаблона. В таком случае я надеялся, что вычет аргумента шаблона будет отправлен.

Итак, мой вопрос: не является ли это экспресс-разработкой текущей формулировки предложения по выводу аргументов шаблона класса? Или это незаконченная функция или ошибка в текущей реализации функции g ++? И это было бы больше вопросом для авторов предложения или для комитета C++ ISO, но если кто-то из них увидит это: было бы желательно, чтобы окончательная формулировка функции включала включение шаблонов псевдонимов, таких как этот, чтобы есть неявные направляющие для них?

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

Я строю с gcc, построенным из головы только несколько дней назад, используя --std=c++1z, Полная информация о версии: gcc version 7.0.0 20161201 (experimental) (Homebrew gcc HEAD- --with-jit)

2 ответа

Решение

Это была особенность, которую мы рассмотрели при разработке предложения, но в конечном итоге она была сокращена, потому что у нас еще не было достаточно хорошего дизайна для него. В частности, есть некоторые тонкости, касающиеся того, как вы выбираете и преобразуете руководства по вычетам из шаблона с псевдонимом в руководства по вычетам для шаблона псевдонима. Есть также открытые вопросы относительно того, как вести себя, если шаблон псевдонима не является простым псевдонимом для другого шаблона. Некоторые примеры:

template<typename T> struct Q { Q(T); };     // #1
template<typename T> struct Q<T*> { Q(T); }; // #2
template<typename T> using QP = Q<T*>;
int *x;
Q p = x;  // deduces Q<int*> using #1, ill-formed
QP q = x; // deduces Q<int*> using #1, or
          // deduces Q<int**> using #2?

template<typename T> Q(T) -> Q<T>; // #3
QP r = x; // can we use deduction guide #3 here?

template<typename T> Q(T*) -> Q<T**>; // #4
int **y;
QP s = y; // can we use deduction guide #4 here?

template<typename T> struct A { typedef T type; struct Y {}; };
template<typename T> using X = typename A<T>::type;
template<typename T> using Y = typename A<T>::Y;
X x = 4;           // can this deduce T == int?
Y y = A<int>::Y(); // can this deduce T == int?

Есть неплохие ответы на вышеупомянутые вопросы, но решение их добавляет сложность, и казалось предпочтительным запретить вычеты для шаблонов псевдонимов для C++17, а не спешить с ошибками.

Я предсказываю, что мы увидим статью от Faisal, предлагающую эту функцию для C++20.

Из http://en.cppreference.com/w/cpp/language/template_argument_deduction"Шаблоны псевдонимов никогда не выводятся". Итак, это по замыслу.

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