Я считаю, что я нашел проблему с обработкой шаблона gcc alias. По сути, gcc, похоже, не может правильно подставить идентификатор шаблона псевдонима для создания шаблона псевдонима, ссылаясь на типы по ссылке.
Я смог уничтожить беспорядочную проблему реального мира до незначительной вариации на ненормативном примере, представленном в стандартном разделе С++ 11 temp.alias(14.5.7/2):
#include <vector>
using namespace std;
template <class T>
using Vec = vector<T, allocator<T>>;
template <template <class> class TT>
void f1(TT<int> v);
template <template <class> class TT>
void f2(TT<int>& v);
template <template <class, class> class TT>
void g1(TT<int, allocator<int>> v);
template <template <class, class> class TT>
void g2(TT<int, allocator<int>>& v);
void foo()
{
Vec<int> v;
f1(v); // gcc and clang both correctly yield no matching function error
g1(v);
f2(v); // clang yields a no matching function error
g2(v); // gcc yields a no matching function error
}
Как отмечалось выше, clang 3.3 (недавнее вытягивание из svn) и gcc (4.7.2, 4.8.0 и 4.8.1) согласуются с обработкой f1/g1 в соответствии со стандартом, но отличаются при обработке из f2/g2 (чтобы было ясно, что все проверенные версии gcc принимают вызов f2() и ошибку при вызове g2()). Разница между f1/g1 и f2/g2, конечно, состоит в том, что последняя пара использует контрольный параметр.
Все показания, как в этом примере, так и в моей реальной проблеме, состоят в том, что gcc неправильно преобразовывает тип экземпляра шаблона псевдонимов (например, Vec<int>
) в псевдонимы (например, vector<int, allocator<int>>
) до пытаясь вывести параметр шаблона для экземпляров f2 и g2.
Мой вопрос: во-первых, это действительно gcc некорректно и clang правильно здесь, и во-вторых, есть ли простой способ (кроме использования шаблона псевдонима), чтобы убедить gcc отклонить f2 и сопоставить g2.